197 lines · cpp
1//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to the MSP430 assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/MSP430InstPrinter.h"15#include "MSP430MCInstLower.h"16#include "MSP430TargetMachine.h"17#include "TargetInfo/MSP430TargetInfo.h"18#include "llvm/BinaryFormat/ELF.h"19#include "llvm/CodeGen/AsmPrinter.h"20#include "llvm/CodeGen/MachineConstantPool.h"21#include "llvm/CodeGen/MachineInstr.h"22#include "llvm/CodeGen/MachineModuleInfo.h"23#include "llvm/IR/Mangler.h"24#include "llvm/MC/MCAsmInfo.h"25#include "llvm/MC/MCInst.h"26#include "llvm/MC/MCSectionELF.h"27#include "llvm/MC/MCStreamer.h"28#include "llvm/MC/MCSymbol.h"29#include "llvm/MC/TargetRegistry.h"30#include "llvm/Support/Compiler.h"31#include "llvm/Support/raw_ostream.h"32using namespace llvm;33 34#define DEBUG_TYPE "asm-printer"35 36namespace {37 class MSP430AsmPrinter : public AsmPrinter {38 public:39 MSP430AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)40 : AsmPrinter(TM, std::move(Streamer), ID) {}41 42 StringRef getPassName() const override { return "MSP430 Assembly Printer"; }43 44 bool runOnMachineFunction(MachineFunction &MF) override;45 46 void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;47 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,48 bool PrefixHash = true);49 void printSrcMemOperand(const MachineInstr *MI, int OpNum,50 raw_ostream &O);51 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,52 const char *ExtraCode, raw_ostream &O) override;53 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,54 const char *ExtraCode, raw_ostream &O) override;55 void emitInstruction(const MachineInstr *MI) override;56 57 void EmitInterruptVectorSection(MachineFunction &ISR);58 59 static char ID;60 };61} // end of anonymous namespace62 63void MSP430AsmPrinter::PrintSymbolOperand(const MachineOperand &MO,64 raw_ostream &O) {65 uint64_t Offset = MO.getOffset();66 if (Offset)67 O << '(' << Offset << '+';68 69 getSymbol(MO.getGlobal())->print(O, MAI);70 71 if (Offset)72 O << ')';73}74 75void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,76 raw_ostream &O, bool PrefixHash) {77 const MachineOperand &MO = MI->getOperand(OpNum);78 switch (MO.getType()) {79 default: llvm_unreachable("Not implemented yet!");80 case MachineOperand::MO_Register:81 O << MSP430InstPrinter::getRegisterName(MO.getReg());82 return;83 case MachineOperand::MO_Immediate:84 if (PrefixHash)85 O << '#';86 O << MO.getImm();87 return;88 case MachineOperand::MO_MachineBasicBlock:89 MO.getMBB()->getSymbol()->print(O, MAI);90 return;91 case MachineOperand::MO_GlobalAddress: {92 // If the global address expression is a part of displacement field with a93 // register base, we should not emit any prefix symbol here, e.g.94 // mov.w glb(r1), r295 // Otherwise (!) msp430-as will silently miscompile the output :(96 if (PrefixHash)97 O << '#';98 PrintSymbolOperand(MO, O);99 return;100 }101 }102}103 104void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,105 raw_ostream &O) {106 const MachineOperand &Base = MI->getOperand(OpNum);107 const MachineOperand &Disp = MI->getOperand(OpNum+1);108 109 // Print displacement first110 111 // Imm here is in fact global address - print extra modifier.112 if (Disp.isImm() && Base.getReg() == MSP430::SR)113 O << '&';114 printOperand(MI, OpNum + 1, O, /*PrefixHash=*/false);115 116 // Print register base field117 if (Base.getReg() != MSP430::SR && Base.getReg() != MSP430::PC) {118 O << '(';119 printOperand(MI, OpNum, O);120 O << ')';121 }122}123 124/// PrintAsmOperand - Print out an operand for an inline asm expression.125///126bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,127 const char *ExtraCode, raw_ostream &O) {128 // Does this asm operand have a single letter operand modifier?129 if (ExtraCode && ExtraCode[0])130 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);131 132 printOperand(MI, OpNo, O);133 return false;134}135 136bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,137 unsigned OpNo,138 const char *ExtraCode,139 raw_ostream &O) {140 if (ExtraCode && ExtraCode[0]) {141 return true; // Unknown modifier.142 }143 printSrcMemOperand(MI, OpNo, O);144 return false;145}146 147//===----------------------------------------------------------------------===//148void MSP430AsmPrinter::emitInstruction(const MachineInstr *MI) {149 MSP430_MC::verifyInstructionPredicates(MI->getOpcode(),150 getSubtargetInfo().getFeatureBits());151 152 MSP430MCInstLower MCInstLowering(OutContext, *this);153 154 MCInst TmpInst;155 MCInstLowering.Lower(MI, TmpInst);156 EmitToStreamer(*OutStreamer, TmpInst);157}158 159void MSP430AsmPrinter::EmitInterruptVectorSection(MachineFunction &ISR) {160 MCSection *Cur = OutStreamer->getCurrentSectionOnly();161 const auto *F = &ISR.getFunction();162 if (F->getCallingConv() != CallingConv::MSP430_INTR) {163 report_fatal_error("Functions with 'interrupt' attribute must have msp430_intrcc CC");164 }165 StringRef IVIdx = F->getFnAttribute("interrupt").getValueAsString();166 MCSection *IV = OutStreamer->getContext().getELFSection(167 "__interrupt_vector_" + IVIdx,168 ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);169 OutStreamer->switchSection(IV);170 171 const MCSymbol *FunctionSymbol = getSymbol(F);172 OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());173 OutStreamer->switchSection(Cur);174}175 176bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {177 // Emit separate section for an interrupt vector if ISR178 if (MF.getFunction().hasFnAttribute("interrupt")) {179 EmitInterruptVectorSection(MF);180 }181 182 SetupMachineFunction(MF);183 emitFunctionBody();184 return false;185}186 187char MSP430AsmPrinter::ID = 0;188 189INITIALIZE_PASS(MSP430AsmPrinter, "msp430-asm-printer",190 "MSP430 Assembly Printer", false, false)191 192// Force static initialization.193extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void194LLVMInitializeMSP430AsmPrinter() {195 RegisterAsmPrinter<MSP430AsmPrinter> X(getTheMSP430Target());196}197