diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 1c42f44765abf..7ba1db496ec11 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -102,6 +102,35 @@ void ARMAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) { OutStreamer->emitValue(E, Size); } +// An alias to a cmse entry function should also emit a `__acle_se_` symbol. +void ARMAsmPrinter::emitCMSEVeneerAlias(const GlobalAlias &GA) { + const Function *BaseFn = dyn_cast_or_null(GA.getAliaseeObject()); + if (!BaseFn || !BaseFn->hasFnAttribute("cmse_nonsecure_entry")) + return; + + MCSymbol *AliasSym = getSymbol(&GA); + MCSymbol *FnSym = getSymbol(BaseFn); + + MCSymbol *SEAliasSym = + OutContext.getOrCreateSymbol(Twine("__acle_se_") + AliasSym->getName()); + MCSymbol *SEBaseSym = + OutContext.getOrCreateSymbol(Twine("__acle_se_") + FnSym->getName()); + + // Mirror alias linkage/visibility onto the veneer-alias symbol. + emitLinkage(&GA, SEAliasSym); + OutStreamer->emitSymbolAttribute(SEAliasSym, MCSA_ELF_TypeFunction); + emitVisibility(SEAliasSym, GA.getVisibility()); + + // emit "__acle_se_ = __acle_se_" + const MCExpr *SEExpr = MCSymbolRefExpr::create(SEBaseSym, OutContext); + OutStreamer->emitAssignment(SEAliasSym, SEExpr); +} + +void ARMAsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) { + AsmPrinter::emitGlobalAlias(M, GA); + ARMAsmPrinter::emitCMSEVeneerAlias(GA); +} + void ARMAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (PromotedGlobals.count(GV)) // The global was promoted into a constant pool. It should not be emitted. diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h index 2b067c753264f..93f9478370645 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.h +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h @@ -108,6 +108,7 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { void emitEndOfAsmFile(Module &M) override; void emitXXStructor(const DataLayout &DL, const Constant *CV) override; void emitGlobalVariable(const GlobalVariable *GV) override; + void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override; MCSymbol *GetCPISymbol(unsigned CPID) const override; @@ -152,6 +153,8 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { MCSymbol *GetARMGVSymbol(const GlobalValue *GV, unsigned char TargetFlags); + void emitCMSEVeneerAlias(const GlobalAlias &GA); + public: /// EmitMachineConstantPoolValue - Print a machine constantpool value to /// the .s file. diff --git a/llvm/test/CodeGen/ARM/cmse-entry-alias.ll b/llvm/test/CodeGen/ARM/cmse-entry-alias.ll new file mode 100644 index 0000000000000..2949f1e21a4b4 --- /dev/null +++ b/llvm/test/CodeGen/ARM/cmse-entry-alias.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple=thumbv8.1m.main %s -o - | FileCheck %s + +@foo = unnamed_addr alias void (), ptr @bar + +; CHECK: .globl bar +; CHECK: .globl __acle_se_bar @ @bar +; CHECK: .globl foo +; CHECK: foo = bar +; CHECK: __acle_se_foo = __acle_se_bar + +define dso_local void @bar() unnamed_addr #0 { +start: + ret void +} + +attributes #0 = { nounwind "cmse_nonsecure_entry" } +