diff options
Diffstat (limited to 'lib/Target/MSP430/MSP430AsmPrinter.cpp')
| -rw-r--r-- | lib/Target/MSP430/MSP430AsmPrinter.cpp | 85 |
1 files changed, 57 insertions, 28 deletions
diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp index f39c21fc8aa2..3a71a084d1af 100644 --- a/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -1,9 +1,8 @@ //===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -12,11 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "InstPrinter/MSP430InstPrinter.h" +#include "MCTargetDesc/MSP430InstPrinter.h" #include "MSP430.h" #include "MSP430InstrInfo.h" #include "MSP430MCInstLower.h" #include "MSP430TargetMachine.h" +#include "TargetInfo/MSP430TargetInfo.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -28,6 +29,7 @@ #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/TargetRegistry.h" @@ -44,20 +46,34 @@ namespace { StringRef getPassName() const override { return "MSP430 Assembly Printer"; } + bool runOnMachineFunction(MachineFunction &MF) override; + + void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = nullptr); void printSrcMemOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O) override; - bool PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) override; + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) override; void EmitInstruction(const MachineInstr *MI) override; + + void EmitInterruptVectorSection(MachineFunction &ISR); }; } // end of anonymous namespace +void MSP430AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, + raw_ostream &O) { + uint64_t Offset = MO.getOffset(); + if (Offset) + O << '(' << Offset << '+'; + + getSymbol(MO.getGlobal())->print(O, MAI); + + if (Offset) + O << ')'; +} void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char *Modifier) { @@ -76,25 +92,13 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, MO.getMBB()->getSymbol()->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: { - bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - uint64_t Offset = MO.getOffset(); - // If the global address expression is a part of displacement field with a // register base, we should not emit any prefix symbol here, e.g. - // mov.w &foo, r1 - // vs // mov.w glb(r1), r2 // Otherwise (!) msp430-as will silently miscompile the output :( if (!Modifier || strcmp(Modifier, "nohash")) - O << (isMemOp ? '&' : '#'); - if (Offset) - O << '(' << Offset << '+'; - - getSymbol(MO.getGlobal())->print(O, MAI); - - if (Offset) - O << ')'; - + O << '#'; + PrintSymbolOperand(MO, O); return; } } @@ -108,12 +112,12 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, // Print displacement first // Imm here is in fact global address - print extra modifier. - if (Disp.isImm() && !Base.getReg()) + if (Disp.isImm() && Base.getReg() == MSP430::SR) O << '&'; printOperand(MI, OpNum+1, O, "nohash"); // Print register base field - if (Base.getReg()) { + if (Base.getReg() != MSP430::SR && Base.getReg() != MSP430::PC) { O << '('; printOperand(MI, OpNum, O); O << ')'; @@ -123,18 +127,17 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. + return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); printOperand(MI, OpNo, O); return false; } bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, + unsigned OpNo, const char *ExtraCode, raw_ostream &O) { if (ExtraCode && ExtraCode[0]) { @@ -153,6 +156,32 @@ void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); } +void MSP430AsmPrinter::EmitInterruptVectorSection(MachineFunction &ISR) { + MCSection *Cur = OutStreamer->getCurrentSectionOnly(); + const auto *F = &ISR.getFunction(); + assert(F->hasFnAttribute("interrupt") && + "Functions with MSP430_INTR CC should have 'interrupt' attribute"); + StringRef IVIdx = F->getFnAttribute("interrupt").getValueAsString(); + MCSection *IV = OutStreamer->getContext().getELFSection( + "__interrupt_vector_" + IVIdx, + ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); + OutStreamer->SwitchSection(IV); + + const MCSymbol *FunctionSymbol = getSymbol(F); + OutStreamer->EmitSymbolValue(FunctionSymbol, TM.getProgramPointerSize()); + OutStreamer->SwitchSection(Cur); +} + +bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { + // Emit separate section for an interrupt vector if ISR + if (MF.getFunction().getCallingConv() == CallingConv::MSP430_INTR) + EmitInterruptVectorSection(MF); + + SetupMachineFunction(MF); + EmitFunctionBody(); + return false; +} + // Force static initialization. extern "C" void LLVMInitializeMSP430AsmPrinter() { RegisterAsmPrinter<MSP430AsmPrinter> X(getTheMSP430Target()); |
