Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
35266 views
//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a printer that converts from our internal representation9// of machine-dependent LLVM code to the MSP430 assembly language.10//11//===----------------------------------------------------------------------===//1213#include "MCTargetDesc/MSP430InstPrinter.h"14#include "MSP430.h"15#include "MSP430InstrInfo.h"16#include "MSP430MCInstLower.h"17#include "MSP430TargetMachine.h"18#include "TargetInfo/MSP430TargetInfo.h"19#include "llvm/BinaryFormat/ELF.h"20#include "llvm/CodeGen/AsmPrinter.h"21#include "llvm/CodeGen/MachineConstantPool.h"22#include "llvm/CodeGen/MachineFunctionPass.h"23#include "llvm/CodeGen/MachineInstr.h"24#include "llvm/CodeGen/MachineModuleInfo.h"25#include "llvm/IR/Constants.h"26#include "llvm/IR/DerivedTypes.h"27#include "llvm/IR/Mangler.h"28#include "llvm/IR/Module.h"29#include "llvm/MC/MCAsmInfo.h"30#include "llvm/MC/MCInst.h"31#include "llvm/MC/MCSectionELF.h"32#include "llvm/MC/MCStreamer.h"33#include "llvm/MC/MCSymbol.h"34#include "llvm/MC/TargetRegistry.h"35#include "llvm/Support/raw_ostream.h"36using namespace llvm;3738#define DEBUG_TYPE "asm-printer"3940namespace {41class MSP430AsmPrinter : public AsmPrinter {42public:43MSP430AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)44: AsmPrinter(TM, std::move(Streamer)) {}4546StringRef getPassName() const override { return "MSP430 Assembly Printer"; }4748bool runOnMachineFunction(MachineFunction &MF) override;4950void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;51void printOperand(const MachineInstr *MI, int OpNum,52raw_ostream &O, const char* Modifier = nullptr);53void printSrcMemOperand(const MachineInstr *MI, int OpNum,54raw_ostream &O);55bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,56const char *ExtraCode, raw_ostream &O) override;57bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,58const char *ExtraCode, raw_ostream &O) override;59void emitInstruction(const MachineInstr *MI) override;6061void EmitInterruptVectorSection(MachineFunction &ISR);62};63} // end of anonymous namespace6465void MSP430AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,66raw_ostream &O) {67uint64_t Offset = MO.getOffset();68if (Offset)69O << '(' << Offset << '+';7071getSymbol(MO.getGlobal())->print(O, MAI);7273if (Offset)74O << ')';75}7677void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,78raw_ostream &O, const char *Modifier) {79const MachineOperand &MO = MI->getOperand(OpNum);80switch (MO.getType()) {81default: llvm_unreachable("Not implemented yet!");82case MachineOperand::MO_Register:83O << MSP430InstPrinter::getRegisterName(MO.getReg());84return;85case MachineOperand::MO_Immediate:86if (!Modifier || strcmp(Modifier, "nohash"))87O << '#';88O << MO.getImm();89return;90case MachineOperand::MO_MachineBasicBlock:91MO.getMBB()->getSymbol()->print(O, MAI);92return;93case MachineOperand::MO_GlobalAddress: {94// If the global address expression is a part of displacement field with a95// register base, we should not emit any prefix symbol here, e.g.96// mov.w glb(r1), r297// Otherwise (!) msp430-as will silently miscompile the output :(98if (!Modifier || strcmp(Modifier, "nohash"))99O << '#';100PrintSymbolOperand(MO, O);101return;102}103}104}105106void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,107raw_ostream &O) {108const MachineOperand &Base = MI->getOperand(OpNum);109const MachineOperand &Disp = MI->getOperand(OpNum+1);110111// Print displacement first112113// Imm here is in fact global address - print extra modifier.114if (Disp.isImm() && Base.getReg() == MSP430::SR)115O << '&';116printOperand(MI, OpNum+1, O, "nohash");117118// Print register base field119if (Base.getReg() != MSP430::SR && Base.getReg() != MSP430::PC) {120O << '(';121printOperand(MI, OpNum, O);122O << ')';123}124}125126/// PrintAsmOperand - Print out an operand for an inline asm expression.127///128bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,129const char *ExtraCode, raw_ostream &O) {130// Does this asm operand have a single letter operand modifier?131if (ExtraCode && ExtraCode[0])132return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);133134printOperand(MI, OpNo, O);135return false;136}137138bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,139unsigned OpNo,140const char *ExtraCode,141raw_ostream &O) {142if (ExtraCode && ExtraCode[0]) {143return true; // Unknown modifier.144}145printSrcMemOperand(MI, OpNo, O);146return false;147}148149//===----------------------------------------------------------------------===//150void MSP430AsmPrinter::emitInstruction(const MachineInstr *MI) {151MSP430_MC::verifyInstructionPredicates(MI->getOpcode(),152getSubtargetInfo().getFeatureBits());153154MSP430MCInstLower MCInstLowering(OutContext, *this);155156MCInst TmpInst;157MCInstLowering.Lower(MI, TmpInst);158EmitToStreamer(*OutStreamer, TmpInst);159}160161void MSP430AsmPrinter::EmitInterruptVectorSection(MachineFunction &ISR) {162MCSection *Cur = OutStreamer->getCurrentSectionOnly();163const auto *F = &ISR.getFunction();164if (F->getCallingConv() != CallingConv::MSP430_INTR) {165report_fatal_error("Functions with 'interrupt' attribute must have msp430_intrcc CC");166}167StringRef IVIdx = F->getFnAttribute("interrupt").getValueAsString();168MCSection *IV = OutStreamer->getContext().getELFSection(169"__interrupt_vector_" + IVIdx,170ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);171OutStreamer->switchSection(IV);172173const MCSymbol *FunctionSymbol = getSymbol(F);174OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());175OutStreamer->switchSection(Cur);176}177178bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {179// Emit separate section for an interrupt vector if ISR180if (MF.getFunction().hasFnAttribute("interrupt")) {181EmitInterruptVectorSection(MF);182}183184SetupMachineFunction(MF);185emitFunctionBody();186return false;187}188189// Force static initialization.190extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmPrinter() {191RegisterAsmPrinter<MSP430AsmPrinter> X(getTheMSP430Target());192}193194195