Index: lib/MC/MCSectionELF.cpp =================================================================== --- lib/MC/MCSectionELF.cpp +++ lib/MC/MCSectionELF.cpp @@ -113,7 +113,7 @@ OS << 'c'; if (Flags & ELF::XCORE_SHF_DP_SECTION) OS << 'd'; - } else if (T.isARM() || T.isThumb()) { + } else if (T.isARM() || T.isThumb() || T.isAArch64() ) { if (Flags & ELF::SHF_ARM_PURECODE) OS << 'y'; } Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -500,6 +500,9 @@ BCase(SHF_TLS); BCase(SHF_COMPRESSED); switch (Object->Header.Machine) { + case ELF::EM_AARCH64: + BCase(SHF_ARM_PURECODE); + break; case ELF::EM_ARM: BCase(SHF_ARM_PURECODE); break; Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -83,6 +83,10 @@ def FeatureUseAA : SubtargetFeature<"use-aa", "UseAA", "true", "Use alias analysis during codegen">; +def FeatureExecuteOnly + : SubtargetFeature<"execute-only", "GenExecuteOnly", "true", + "Enable the generation of execute only code.">; + def FeatureBalanceFPOps : SubtargetFeature<"balance-fp-ops", "BalanceFPOps", "true", "balance mix of odd and even D-registers for fp multiply(-accumulate) ops">; Index: lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- lib/Target/AArch64/AArch64AsmPrinter.cpp +++ lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -74,7 +74,7 @@ /// Wrapper for MCInstLowering.lowerOperand() for the /// tblgen'erated pseudo lowering. bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const { - return MCInstLowering.lowerOperand(MO, MCOp); + return MCInstLowering.lowerOperand(MO, MCOp, STI); } void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, @@ -601,7 +601,7 @@ } case AArch64::TCRETURNdi: { MCOperand Dest; - MCInstLowering.lowerOperand(MI->getOperand(0), Dest); + MCInstLowering.lowerOperand(MI->getOperand(0), Dest, STI); MCInst TmpInst; TmpInst.setOpcode(AArch64::B); TmpInst.addOperand(Dest); @@ -621,9 +621,9 @@ MCOperand Sym, SymTLSDescLo12, SymTLSDesc; MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF); MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE); - MCInstLowering.lowerOperand(MO_Sym, Sym); - MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12); - MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc); + MCInstLowering.lowerOperand(MO_Sym, Sym, STI); + MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12, STI); + MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc, STI); MCInst Adrp; Adrp.setOpcode(AArch64::ADRP); Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2763,6 +2763,8 @@ case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::ConstantPool: + if (Subtarget->genExecuteOnly()) + llvm_unreachable("execute-only should not generate constant pools"); return LowerConstantPool(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -51,6 +51,7 @@ def IsLE : Predicate<"Subtarget->isLittleEndian()">; def IsBE : Predicate<"!Subtarget->isLittleEndian()">; +def GenExecuteOnly : Predicate<"Subtarget->genExecuteOnly()">; def UseAlternateSExtLoadCVTF32 : Predicate<"Subtarget->useAlternateSExtLoadCVTF32Pattern()">; Index: lib/Target/AArch64/AArch64MCInstLower.h =================================================================== --- lib/Target/AArch64/AArch64MCInstLower.h +++ lib/Target/AArch64/AArch64MCInstLower.h @@ -11,6 +11,7 @@ #define LLVM_LIB_TARGET_AARCH64_AARCH64MCINSTLOWER_H #include "llvm/ADT/Triple.h" +#include "AArch64Subtarget.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -35,7 +36,8 @@ public: AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer); - bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const; + bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp, + const AArch64Subtarget* ST) const; void Lower(const MachineInstr *MI, MCInst &OutMI) const; MCOperand lowerSymbolOperandDarwin(const MachineOperand &MO, Index: lib/Target/AArch64/AArch64MCInstLower.cpp =================================================================== --- lib/Target/AArch64/AArch64MCInstLower.cpp +++ lib/Target/AArch64/AArch64MCInstLower.cpp @@ -202,7 +202,8 @@ } bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, - MCOperand &MCOp) const { + MCOperand &MCOp, + const AArch64Subtarget *STI) const { switch (MO.getType()) { default: llvm_unreachable("unknown operand type"); @@ -235,6 +236,8 @@ MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); break; case MachineOperand::MO_ConstantPoolIndex: + if (STI->genExecuteOnly()) + llvm_unreachable("execute-only should not generate constant pools"); MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); break; case MachineOperand::MO_BlockAddress: @@ -250,7 +253,9 @@ for (const MachineOperand &MO : MI->operands()) { MCOperand MCOp; - if (lowerOperand(MO, MCOp)) + const AArch64Subtarget *STI = + static_cast(&MI->getMF()->getSubtarget()); + if (lowerOperand(MO, MCOp, STI)) OutMI.addOperand(MCOp); } } Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -63,6 +63,9 @@ /// ARMProcFamily - ARM processor family: Cortex-A53, Cortex-A57, and others. ARMProcFamilyEnum ARMProcFamily = Others; + // Generate code that does not contain data access to code sections. + bool GenExecuteOnly = false; + bool HasV8_1aOps = false; bool HasV8_2aOps = false; bool HasV8_3aOps = false; @@ -161,6 +164,9 @@ void initializeProperties(); public: + + bool genExecuteOnly() const { return GenExecuteOnly; } + /// This constructor initializes the data members to match that /// of the specified triple. AArch64Subtarget(const Triple &TT, const std::string &CPU, Index: lib/Target/AArch64/AArch64TargetObjectFile.h =================================================================== --- lib/Target/AArch64/AArch64TargetObjectFile.h +++ lib/Target/AArch64/AArch64TargetObjectFile.h @@ -18,7 +18,15 @@ /// This implementation is used for AArch64 ELF targets (Linux in particular). class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF { - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; + + public: + MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + + MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, + const TargetMachine &TM) const override; + }; /// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin. Index: lib/Target/AArch64/AArch64TargetObjectFile.cpp =================================================================== --- lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/Mangler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCValue.h" using namespace llvm; @@ -78,3 +79,34 @@ // be accessed via at least a linker-private symbol. getMangler().getNameWithPrefix(OutName, GV, /* CannotUsePrivateLabel */ true); } + +static bool isExecuteOnlyFunction(const GlobalObject *GO, SectionKind SK, + const TargetMachine &TM) { + if (const Function *F = dyn_cast(GO)){ + if (TM.getSubtarget(*F).genExecuteOnly() && SK.isText()){ + return true; + } + } + return false; +} + + +MCSection * +AArch64_ELFTargetObjectFile::getExplicitSectionGlobal( + const GlobalObject *GO, SectionKind SK, const TargetMachine &TM) const { + // Set execute-only access for the explicit section + if (isExecuteOnlyFunction(GO, SK, TM)) + SK = SectionKind::getExecuteOnly(); + + return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, SK, TM); +} + +MCSection * +AArch64_ELFTargetObjectFile::SelectSectionForGlobal( + const GlobalObject *GO, SectionKind SK, const TargetMachine &TM) const { + // Place the global in the execute-only text section + if (isExecuteOnlyFunction(GO, SK, TM)) + SK = SectionKind::getExecuteOnly(); + + return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, SK, TM); +} Index: test/CodeGen/AArch64/execute-only-section.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/execute-only-section.ll @@ -0,0 +1,21 @@ +; RUN: llc < %s -mtriple=aarch64 -mattr=+execute-only %s -o - | FileCheck %s + +; CHECK: .section .text,"axy",@progbits,unique,0 +; CHECK-NOT: .section +; CHECK-NOT: .text +; CHECK: .globl test_SectionForGlobal +; CHECK: .type test_SectionForGlobal,@function +define void @test_SectionForGlobal() { +entry: + ret void +} + +; CHECK: .section .test,"axy",@progbits +; CHECK-NOT: .section +; CHECK-NOT: .text +; CHECK: .globl test_ExplicitSectionForGlobal +; CHECK: .type test_ExplicitSectionForGlobal,@function +define void @test_ExplicitSectionForGlobal() section ".test" { +entry: + ret void +} Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -1102,6 +1102,10 @@ LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) }; +static const EnumEntry ElfAArch64SectionFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) +}; + static const EnumEntry ElfHexagonSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL) }; @@ -4053,6 +4057,10 @@ SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), std::end(ElfARMSectionFlags)); break; + case EM_AARCH64: + SectionFlags.insert(SectionFlags.end(), std::begin(ElfAArch64SectionFlags), + std::end(ElfAArch64SectionFlags)); + break; case EM_HEXAGON: SectionFlags.insert(SectionFlags.end(), std::begin(ElfHexagonSectionFlags),