From: Anton Korobeynikov Date: Wed, 16 Jan 2019 14:03:41 +0000 (+0000) Subject: [MSP430] Emit a separate section for every interrupt vector X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5d37f6c75626db314b8dbf06231c8ffb502189fb;p=llvm [MSP430] Emit a separate section for every interrupt vector This is LLVM part of D56663 Linker scripts shipped by TI require to have every interrupt vector in a separate section with a specific name: SECTIONS { __interrupt_vector_XX : { KEEP (*(__interrupt_vector_XX )) } > VECTXX ... } Follow the requirement emit the section for every vector which contain address of interrupt handler: .section __interrupt_vector_XX,"ax",@progbits .word %isr% Patch by Kristina Bessonova! Differential Revision: https://reviews.llvm.org/D56664 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351345 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp index f39c21fc8aa..5e9b108c2de 100644 --- a/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -17,6 +17,7 @@ #include "MSP430InstrInfo.h" #include "MSP430MCInstLower.h" #include "MSP430TargetMachine.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,6 +46,8 @@ namespace { StringRef getPassName() const override { return "MSP430 Assembly Printer"; } + bool runOnMachineFunction(MachineFunction &MF) override; + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = nullptr); void printSrcMemOperand(const MachineInstr *MI, int OpNum, @@ -55,6 +59,8 @@ namespace { unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) override; void EmitInstruction(const MachineInstr *MI) override; + + void EmitInterruptVectorSection(MachineFunction &ISR); }; } // end of anonymous namespace @@ -153,6 +159,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 X(getTheMSP430Target()); diff --git a/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll b/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll index c3d69c7c0db..be82e98dffe 100644 --- a/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll +++ b/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll @@ -3,7 +3,7 @@ target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8" target triple = "msp430-unknown-linux-gnu" -define msp430_intrcc void @foo() nounwind { +define msp430_intrcc void @foo() nounwind #0 { entry: %fa = call i8* @llvm.frameaddress(i32 0) store i8 0, i8* %fa @@ -11,3 +11,5 @@ entry: } declare i8* @llvm.frameaddress(i32) + +attributes #0 = { noinline nounwind optnone "interrupt"="2" } diff --git a/test/CodeGen/MSP430/fp.ll b/test/CodeGen/MSP430/fp.ll index e7d7c519657..bf603704a91 100644 --- a/test/CodeGen/MSP430/fp.ll +++ b/test/CodeGen/MSP430/fp.ll @@ -27,3 +27,5 @@ define msp430_intrcc void @fpb_alloced() #0 { call void asm sideeffect "nop", "r"(i8 0) ret void } + +attributes #0 = { noinline nounwind optnone "interrupt"="2" } diff --git a/test/CodeGen/MSP430/interrupt.ll b/test/CodeGen/MSP430/interrupt.ll index 5fa0c849c26..94fb3bc457a 100644 --- a/test/CodeGen/MSP430/interrupt.ll +++ b/test/CodeGen/MSP430/interrupt.ll @@ -13,6 +13,9 @@ target triple = "msp430-generic-generic" ; instruction RETI, which restores the SR register and branches to the PC where ; the interrupt occurred. +; CHECK: .section __interrupt_vector_2,"ax",@progbits +; CHECK-NEXT: .short ISR + @g = global float 0.0 define msp430_intrcc void @ISR() #0 { @@ -47,3 +50,4 @@ entry: ret void } +attributes #0 = { noinline nounwind optnone "interrupt"="2" }