[llvm] r289784 - [ARM] Implement execute-only support in CodeGen

Prakhar Bahuguna via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 14 23:59:09 PST 2016


Author: prakhar
Date: Thu Dec 15 01:59:08 2016
New Revision: 289784

URL: http://llvm.org/viewvc/llvm-project?rev=289784&view=rev
Log:
[ARM] Implement execute-only support in CodeGen

This implements execute-only support for ARM code generation, which
prevents the compiler from generating data accesses to code sections.
The following changes are involved:

* Add the CodeGen option "-arm-execute-only" to the ARM code generator.
* Add the clang flag "-mexecute-only" as well as the GCC-compatible
  alias "-mpure-code" to enable this option.
* When enabled, literal pools are replaced with MOVW/MOVT instructions,
  with VMOV used in addition for floating-point literals. As the MOVT
  instruction is required, execute-only support is only available in
  Thumb mode for targets supporting ARMv8-M baseline or Thumb2.
* Jump tables are placed in data sections when in execute-only mode.
* The execute-only text section is assigned section ID 0, and is
  marked as unreadable with the SHF_ARM_PURECODE flag with symbol 'y'.
  This also overrides selection of ELF sections for globals.

Added:
    llvm/trunk/test/CodeGen/ARM/execute-only-big-stack-frame.ll
    llvm/trunk/test/CodeGen/ARM/execute-only-section.ll
    llvm/trunk/test/CodeGen/ARM/execute-only.ll
    llvm/trunk/test/MC/ELF/ARM/execute-only-section.s
Modified:
    llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
    llvm/trunk/include/llvm/MC/SectionKind.h
    llvm/trunk/include/llvm/Support/ELF.h
    llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/trunk/lib/MC/MCContext.cpp
    llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp
    llvm/trunk/lib/MC/MCSectionELF.cpp
    llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
    llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp
    llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp
    llvm/trunk/lib/Target/ARM/ARMSubtarget.h
    llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.cpp
    llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.h
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp
    llvm/trunk/test/CodeGen/ARM/constantfp.ll
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp

Modified: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h Thu Dec 15 01:59:08 2016
@@ -33,7 +33,7 @@ namespace llvm {
 
 class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
   bool UseInitArray;
-  mutable unsigned NextUniqueID = 0;
+  mutable unsigned NextUniqueID = 1;  // ID 0 is reserved for execute-only sections
 
 protected:
   MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =

Modified: llvm/trunk/include/llvm/MC/SectionKind.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/SectionKind.h?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/SectionKind.h (original)
+++ llvm/trunk/include/llvm/MC/SectionKind.h Thu Dec 15 01:59:08 2016
@@ -28,6 +28,9 @@ class SectionKind {
     /// Text - Text section, used for functions and other executable code.
     Text,
 
+           /// ExecuteOnly, Text section that is not readable.
+           ExecuteOnly,
+
     /// ReadOnly - Data that is never written to at program runtime by the
     /// program or the dynamic linker.  Things in the top-level readonly
     /// SectionKind are not mergeable.
@@ -112,7 +115,10 @@ class SectionKind {
 public:
 
   bool isMetadata() const { return K == Metadata; }
-  bool isText() const { return K == Text; }
+
+  bool isText() const { return K == Text || K == ExecuteOnly; }
+
+  bool isExecuteOnly() const { return K == ExecuteOnly; }
 
   bool isReadOnly() const {
     return K == ReadOnly || isMergeableCString() ||
@@ -172,6 +178,7 @@ public:
 
   static SectionKind getMetadata() { return get(Metadata); }
   static SectionKind getText() { return get(Text); }
+  static SectionKind getExecuteOnly() { return get(ExecuteOnly); }
   static SectionKind getReadOnly() { return get(ReadOnly); }
   static SectionKind getMergeable1ByteCString() {
     return get(Mergeable1ByteCString);

Modified: llvm/trunk/include/llvm/Support/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ELF.h?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ELF.h (original)
+++ llvm/trunk/include/llvm/Support/ELF.h Thu Dec 15 01:59:08 2016
@@ -804,6 +804,9 @@ enum : unsigned {
   // Section data is string data by default.
   SHF_MIPS_STRING = 0x80000000,
 
+  // Make code section unreadable when in execute-only mode
+  SHF_ARM_PURECODE = 0x20000000,
+
   SHF_AMDGPU_HSA_GLOBAL = 0x00100000,
   SHF_AMDGPU_HSA_READONLY = 0x00200000,
   SHF_AMDGPU_HSA_CODE = 0x00400000,

Modified: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Thu Dec 15 01:59:08 2016
@@ -181,6 +181,9 @@ static unsigned getELFSectionFlags(Secti
   if (K.isText())
     Flags |= ELF::SHF_EXECINSTR;
 
+  if (K.isExecuteOnly())
+    Flags |= ELF::SHF_ARM_PURECODE;
+
   if (K.isWriteable())
     Flags |= ELF::SHF_WRITE;
 
@@ -312,6 +315,9 @@ selectELFSectionForGlobal(MCContext &Ctx
     UniqueID = *NextUniqueID;
     (*NextUniqueID)++;
   }
+  // Use 0 as the unique ID for execute-only text
+  if (Kind.isExecuteOnly())
+    UniqueID = 0;
   return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
                            EntrySize, Group, UniqueID);
 }

Modified: llvm/trunk/lib/MC/MCContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCContext.cpp (original)
+++ llvm/trunk/lib/MC/MCContext.cpp Thu Dec 15 01:59:08 2016
@@ -368,7 +368,9 @@ MCSectionELF *MCContext::getELFSection(c
   StringRef CachedName = Entry.first.SectionName;
 
   SectionKind Kind;
-  if (Flags & ELF::SHF_EXECINSTR)
+  if (Flags & ELF::SHF_ARM_PURECODE)
+    Kind = SectionKind::getExecuteOnly();
+  else if (Flags & ELF::SHF_EXECINSTR)
     Kind = SectionKind::getText();
   else
     Kind = SectionKind::getReadOnly();

Modified: llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp Thu Dec 15 01:59:08 2016
@@ -293,6 +293,9 @@ static unsigned parseSectionFlags(String
     case 'd':
       flags |= ELF::XCORE_SHF_DP_SECTION;
       break;
+    case 'y':
+      flags |= ELF::SHF_ARM_PURECODE;
+      break;
     case 'G':
       flags |= ELF::SHF_GROUP;
       break;

Modified: llvm/trunk/lib/MC/MCSectionELF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCSectionELF.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCSectionELF.cpp (original)
+++ llvm/trunk/lib/MC/MCSectionELF.cpp Thu Dec 15 01:59:08 2016
@@ -110,6 +110,8 @@ void MCSectionELF::PrintSwitchToSection(
     OS << 'c';
   if (Flags & ELF::XCORE_SHF_DP_SECTION)
     OS << 'd';
+  if (Flags & ELF::SHF_ARM_PURECODE)
+    OS << 'y';
 
   OS << '"';
 

Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Thu Dec 15 01:59:08 2016
@@ -423,6 +423,9 @@ void ScalarBitSetTraits<ELFYAML::ELF_SHF
   BCase(SHF_GROUP)
   BCase(SHF_TLS)
   switch(Object->Header.Machine) {
+  case ELF::EM_ARM:
+    BCase(SHF_ARM_PURECODE)
+    break;
   case ELF::EM_AMDGPU:
     BCase(SHF_AMDGPU_HSA_GLOBAL)
     BCase(SHF_AMDGPU_HSA_READONLY)

Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Thu Dec 15 01:59:08 2016
@@ -232,6 +232,8 @@ void ARMAsmPrinter::printOperand(const M
     break;
   }
   case MachineOperand::MO_ConstantPoolIndex:
+    if (Subtarget->genExecuteOnly())
+      llvm_unreachable("execute-only should not generate constant pools");
     GetCPISymbol(MO.getIndex())->print(O, MAI);
     break;
   }

Modified: llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp Thu Dec 15 01:59:08 2016
@@ -423,7 +423,7 @@ bool ARMConstantIslands::runOnMachineFun
     MadeChange |= optimizeThumb2Branches();
 
   // Optimize jump tables using TBB / TBH.
-  if (GenerateTBB)
+  if (GenerateTBB && !STI->genExecuteOnly())
     MadeChange |= optimizeThumb2JumpTables();
 
   // After a while, this might be made debug-only, but it is not expensive.

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Thu Dec 15 01:59:08 2016
@@ -3152,7 +3152,8 @@ SDValue ARMTargetLowering::LowerGlobalAd
       (isa<GlobalVariable>(GV) && cast<GlobalVariable>(GV)->isConstant()) ||
       isa<Function>(GV);
 
-  if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
+  // promoteToConstantPool only if not generating XO text section
+  if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV) && !Subtarget->genExecuteOnly())
     if (SDValue V = promoteToConstantPool(GV, DAG, PtrVT, dl))
       return V;
 
@@ -4492,10 +4493,10 @@ SDValue ARMTargetLowering::LowerBR_JT(SD
   Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
   Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, dl, PTy));
   SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table);
-  if (Subtarget->isThumb2()) {
-    // Thumb2 uses a two-level jump. That is, it jumps into the jump table
+  if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
+    // Thumb2 and ARMv8-M use a two-level jump. That is, it jumps into the jump table
     // which does another jump to the destination. This also makes it easier
-    // to translate it to TBB / TBH later.
+    // to translate it to TBB / TBH later (Thumb2 only).
     // FIXME: This might not work if the function is extremely large.
     return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
                        Addr, Op.getOperand(2), JTI);
@@ -5571,11 +5572,28 @@ static SDValue isNEONModifiedImm(uint64_
 
 SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG,
                                            const ARMSubtarget *ST) const {
-  if (!ST->hasVFP3())
-    return SDValue();
-
   bool IsDouble = Op.getValueType() == MVT::f64;
   ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
+  const APFloat &FPVal = CFP->getValueAPF();
+
+  // Prevent floating-point constants from using literal loads
+  // when execute-only is enabled.
+  if (ST->genExecuteOnly()) {
+    APInt INTVal = FPVal.bitcastToAPInt();
+    SDLoc DL(CFP);
+    if (IsDouble) {
+      SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32);
+      SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32);
+      if (!ST->isLittle())
+        std::swap(Lo, Hi);
+      return DAG.getNode(ARMISD::VMOVDRR, DL, MVT::f64, Lo, Hi);
+    } else {
+      return DAG.getConstant(INTVal, DL, MVT::i32);
+    }
+  }
+
+  if (!ST->hasVFP3())
+    return SDValue();
 
   // Use the default (constant pool) lowering for double constants when we have
   // an SP-only FPU
@@ -5583,7 +5601,6 @@ SDValue ARMTargetLowering::LowerConstant
     return SDValue();
 
   // Try splatting with a VMOV.f32...
-  const APFloat &FPVal = CFP->getValueAPF();
   int ImmVal = IsDouble ? ARM_AM::getFP64Imm(FPVal) : ARM_AM::getFP32Imm(FPVal);
 
   if (ImmVal != -1) {
@@ -7617,7 +7634,10 @@ SDValue ARMTargetLowering::LowerOperatio
   switch (Op.getOpcode()) {
   default: llvm_unreachable("Don't know how to custom lower this!");
   case ISD::WRITE_REGISTER: return LowerWRITE_REGISTER(Op, DAG);
-  case ISD::ConstantPool:  return LowerConstantPool(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);
   case ISD::GlobalAddress:
     switch (Subtarget->getTargetTriple().getObjectFormat()) {

Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Thu Dec 15 01:59:08 2016
@@ -398,6 +398,14 @@ class tPseudoInst<dag oops, dag iops, in
   list<Predicate> Predicates = [IsThumb];
 }
 
+// PseudoInst that's in ARMv8-M baseline (Somewhere between Thumb and Thumb2)
+class t2basePseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
+                    list<dag> pattern>
+  : PseudoInst<oops, iops, itin, pattern> {
+  let Size = sz;
+  list<Predicate> Predicates = [IsThumb,HasV8MBaseline];
+}
+
 // PseudoInst that's Thumb2-mode only.
 class t2PseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
                     list<dag> pattern>

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Thu Dec 15 01:59:08 2016
@@ -330,6 +330,8 @@ def DontUseVMOVSR : Predicate<"!Subtarge
 def IsLE             : Predicate<"MF->getDataLayout().isLittleEndian()">;
 def IsBE             : Predicate<"MF->getDataLayout().isBigEndian()">;
 
+def GenExecuteOnly : Predicate<"Subtarget->genExecuteOnly()">;
+
 //===----------------------------------------------------------------------===//
 // ARM Flag Definitions.
 

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Thu Dec 15 01:59:08 2016
@@ -3381,7 +3381,9 @@ def t2B   : T2I<(outs), (ins thumb_br_ta
 }
 
 let Size = 4, isNotDuplicable = 1, isIndirectBranch = 1 in {
-def t2BR_JT : t2PseudoInst<(outs),
+
+// available in both v8-M.Baseline and Thumb2 targets
+def t2BR_JT : t2basePseudoInst<(outs),
           (ins GPR:$target, GPR:$index, i32imm:$jt),
            0, IIC_Br,
           [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt)]>,

Modified: llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMMCInstLower.cpp Thu Dec 15 01:59:08 2016
@@ -91,6 +91,8 @@ bool ARMAsmPrinter::lowerOperand(const M
     MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
     break;
   case MachineOperand::MO_ConstantPoolIndex:
+    if (Subtarget->genExecuteOnly())
+      llvm_unreachable("execute-only should not generate constant pools");
     MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
     break;
   case MachineOperand::MO_BlockAddress:

Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp Thu Dec 15 01:59:08 2016
@@ -76,6 +76,11 @@ ARMSubtarget &ARMSubtarget::initializeSu
   return *this;
 }
 
+/// EnableExecuteOnly - Enables the generation of execute-only code on supported
+/// targets
+static cl::opt<bool>
+EnableExecuteOnly("arm-execute-only");
+
 ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
                                                         StringRef FS) {
   ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
@@ -90,7 +95,8 @@ ARMSubtarget::ARMSubtarget(const Triple
                            const ARMBaseTargetMachine &TM, bool IsLittle)
     : ARMGenSubtargetInfo(TT, CPU, FS), UseMulOps(UseFusedMulOps),
       CPUString(CPU), IsLittle(IsLittle), TargetTriple(TT), Options(TM.Options),
-      TM(TM), FrameLowering(initializeFrameLowering(CPU, FS)),
+      TM(TM), GenExecuteOnly(EnableExecuteOnly),
+      FrameLowering(initializeFrameLowering(CPU, FS)),
       // At this point initializeSubtargetDependencies has been called so
       // we can query directly.
       InstrInfo(isThumb1Only()
@@ -169,6 +175,10 @@ void ARMSubtarget::initSubtargetFeatures
   // Assert this for now to make the change obvious.
   assert(hasV6T2Ops() || !hasThumb2());
 
+  // Execute only support requires movt support
+  if (genExecuteOnly())
+    assert(hasV8MBaselineOps() && !NoMovt && "Cannot generate execute-only code for this target");
+
   // Keep a pointer to static instruction cost data for the specified CPU.
   SchedModel = getSchedModelForCPU(CPUString);
 
@@ -353,7 +363,7 @@ bool ARMSubtarget::useMovt(const Machine
   // immediates as it is inherently position independent, and may be out of
   // range otherwise.
   return !NoMovt && hasV8MBaselineOps() &&
-         (isTargetWindows() || !MF.getFunction()->optForMinSize());
+         (isTargetWindows() || !MF.getFunction()->optForMinSize() || genExecuteOnly());
 }
 
 bool ARMSubtarget::useFastISel() const {

Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.h?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSubtarget.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.h Thu Dec 15 01:59:08 2016
@@ -301,6 +301,9 @@ protected:
   /// Generate calls via indirect call instructions.
   bool GenLongCalls = false;
 
+  /// Generate code that does not contain data access to code sections.
+  bool GenExecuteOnly = false;
+
   /// Target machine allowed unsafe FP math (such as use of NEON fp)
   bool UnsafeFPMath = false;
 
@@ -494,6 +497,7 @@ public:
   bool useNaClTrap() const { return UseNaClTrap; }
   bool useSjLjEH() const { return UseSjLjEH; }
   bool genLongCalls() const { return GenLongCalls; }
+  bool genExecuteOnly() const { return GenExecuteOnly; }
 
   bool hasFP16() const { return HasFP16; }
   bool hasD16() const { return HasD16; }

Modified: llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.cpp Thu Dec 15 01:59:08 2016
@@ -27,8 +27,10 @@ using namespace dwarf;
 
 void ARMElfTargetObjectFile::Initialize(MCContext &Ctx,
                                         const TargetMachine &TM) {
-  bool isAAPCS_ABI = static_cast<const ARMTargetMachine &>(TM).TargetABI ==
-                     ARMTargetMachine::ARMABI::ARM_ABI_AAPCS;
+  const ARMTargetMachine &ARM_TM = static_cast<const ARMTargetMachine &>(TM);
+  bool isAAPCS_ABI = ARM_TM.TargetABI == ARMTargetMachine::ARMABI::ARM_ABI_AAPCS;
+  genExecuteOnly = ARM_TM.getSubtargetImpl()->genExecuteOnly();
+
   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
   InitializeELF(isAAPCS_ABI);
 
@@ -38,6 +40,16 @@ void ARMElfTargetObjectFile::Initialize(
 
   AttributesSection =
       getContext().getELFSection(".ARM.attributes", ELF::SHT_ARM_ATTRIBUTES, 0);
+
+  // Make code section unreadable when in execute-only mode
+  if (genExecuteOnly) {
+    unsigned  Type = ELF::SHT_PROGBITS;
+    unsigned Flags = ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_ARM_PURECODE;
+    // Since we cannot modify flags for an existing section, we create a new
+    // section with the right flags, and use 0 as the unique ID for
+    // execute-only text
+    TextSection = Ctx.getELFSection(".text", Type, Flags, 0, "", 0U);
+  }
 }
 
 const MCExpr *ARMElfTargetObjectFile::getTTypeGlobalReference(
@@ -58,3 +70,23 @@ getDebugThreadLocalSymbol(const MCSymbol
   return MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_ARM_TLSLDO,
                                  getContext());
 }
+
+MCSection *
+ARMElfTargetObjectFile::getExplicitSectionGlobal(const GlobalObject *GO,
+                                                 SectionKind SK, const TargetMachine &TM) const {
+  // Set execute-only access for the explicit section
+  if (genExecuteOnly && SK.isText())
+    SK = SectionKind::getExecuteOnly();
+
+  return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, SK, TM);
+}
+
+MCSection *
+ARMElfTargetObjectFile::SelectSectionForGlobal(const GlobalObject *GO,
+                                               SectionKind SK, const TargetMachine &TM) const {
+  // Place the global in the execute-only text section
+  if (genExecuteOnly && SK.isText())
+    SK = SectionKind::getExecuteOnly();
+
+  return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, SK, TM);
+}

Modified: llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.h?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMTargetObjectFile.h Thu Dec 15 01:59:08 2016
@@ -18,6 +18,7 @@ class MCContext;
 class TargetMachine;
 
 class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
+  mutable bool genExecuteOnly = false;
 protected:
   const MCSection *AttributesSection;
 public:
@@ -36,6 +37,12 @@ public:
 
   /// \brief Describe a TLS variable address within debug info.
   const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override;
+
+  MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
+                                      const TargetMachine &TM) const override;
+
+  MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
+                                    const TargetMachine &TM) const override;
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Thu Dec 15 01:59:08 2016
@@ -5453,6 +5453,9 @@ bool ARMAsmParser::parseOperand(OperandV
     if (getParser().parseExpression(SubExprVal))
       return true;
     E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+
+    // execute-only: we assume that assembly programmers know what they are
+    // doing and allow literal pool creation here
     Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E));
     return false;
   }

Modified: llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp Thu Dec 15 01:59:08 2016
@@ -126,6 +126,7 @@ static void emitThumbRegPlusImmInReg(
     bool CanChangeCC, const TargetInstrInfo &TII,
     const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) {
   MachineFunction &MF = *MBB.getParent();
+  const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>();
   bool isHigh = !isARMLowRegister(DestReg) ||
                 (BaseReg != 0 && !isARMLowRegister(BaseReg));
   bool isSub = false;
@@ -154,6 +155,9 @@ static void emitThumbRegPlusImmInReg(
     AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
         .addReg(LdReg, RegState::Kill)
         .setMIFlags(MIFlags);
+  } else if (ST.genExecuteOnly()) {
+    BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), LdReg)
+      .addImm(NumBytes).setMIFlags(MIFlags);
   } else
     MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0,
                           MIFlags);
@@ -570,7 +574,7 @@ void ThumbRegisterInfo::eliminateFrameIn
     unsigned TmpReg = MI.getOperand(0).getReg();
     bool UseRR = false;
     if (Opcode == ARM::tLDRspi) {
-      if (FrameReg == ARM::SP)
+      if (FrameReg == ARM::SP || STI.genExecuteOnly())
         emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
                                  Offset, false, TII, *this);
       else {
@@ -594,7 +598,7 @@ void ThumbRegisterInfo::eliminateFrameIn
       bool UseRR = false;
 
       if (Opcode == ARM::tSTRspi) {
-        if (FrameReg == ARM::SP)
+        if (FrameReg == ARM::SP || STI.genExecuteOnly())
           emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
                                    Offset, false, TII, *this);
         else {

Modified: llvm/trunk/test/CodeGen/ARM/constantfp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/constantfp.ll?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/constantfp.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/constantfp.ll Thu Dec 15 01:59:08 2016
@@ -2,6 +2,25 @@
 ; RUN: llc -mtriple=armv7 -mattr=+neon -mcpu=cortex-a8 %s -o - | FileCheck --check-prefix=CHECK-NONEONFP %s
 ; RUN: llc -mtriple=armv7 -mattr=-neon -mcpu=cortex-a8 %s -o - | FileCheck --check-prefix=CHECK-NONEON %s
 
+; RUN: llc -mtriple=thumbv7m -mcpu=cortex-m4 %s -o - \
+; RUN: | FileCheck --check-prefix=CHECK-NO-XO %s
+
+; RUN: llc -mtriple=thumbv7m -arm-execute-only -mcpu=cortex-m4 %s -o - \
+; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE %s
+
+; RUN: llc -mtriple=thumbv7meb -arm-execute-only -mcpu=cortex-m4 %s -o - \
+; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE-BE %s
+
+; RUN: llc -mtriple=thumbv8m.main -mattr=fp-armv8 %s -o - \
+; RUN: | FileCheck --check-prefix=CHECK-NO-XO %s
+
+; RUN: llc -mtriple=thumbv8m.main -arm-execute-only -mattr=fp-armv8 %s -o - \
+; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE %s
+
+; RUN: llc -mtriple=thumbv8m.maineb -arm-execute-only -mattr=fp-armv8 %s -o - \
+; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE-BE %s
+
+
 define arm_aapcs_vfpcc float @test_vmov_f32() {
 ; CHECK-LABEL: test_vmov_f32:
 ; CHECK: vmov.f32 d0, #1.0
@@ -16,6 +35,14 @@ define arm_aapcs_vfpcc float @test_vmov_
 
 ; CHECK-NONEON-LABEL: test_vmov_imm:
 ; CHECK-NONEON: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-NO-XO-LABEL: test_vmov_imm:
+; CHECK-NO-XO: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-FLOAT-LABEL: test_vmov_imm:
+; CHECK-XO-FLOAT: movs [[REG:r[0-9]+]], #0
+; CHECK-XO-FLOAT: vmov {{s[0-9]+}}, [[REG]]
+; CHECK-XO-FLOAT-NOT: vldr
   ret float 0.0
 }
 
@@ -25,6 +52,14 @@ define arm_aapcs_vfpcc float @test_vmvn_
 
 ; CHECK-NONEON-LABEL: test_vmvn_imm:
 ; CHECK-NONEON: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-NO-XO-LABEL: test_vmvn_imm:
+; CHECK-NO-XO: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-FLOAT-LABEL: test_vmvn_imm:
+; CHECK-XO-FLOAT: mvn [[REG:r[0-9]+]], #-1342177280
+; CHECK-XO-FLOAT: vmov {{s[0-9]+}}, [[REG]]
+; CHECK-XO-FLOAT-NOT: vldr
   ret float 8589934080.0
 }
 
@@ -44,6 +79,19 @@ define arm_aapcs_vfpcc double @test_vmov
 
 ; CHECK-NONEON-LABEL: test_vmov_double_imm:
 ; CHECK-NONEON: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-NO-XO-LABEL: test_vmov_double_imm:
+; CHECK-NO-XO: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-DOUBLE-LABEL: test_vmov_double_imm:
+; CHECK-XO-DOUBLE: movs [[REG:r[0-9]+]], #0
+; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
+; CHECK-XO-DOUBLE-NOT: vldr
+
+; CHECK-XO-DOUBLE-BE-LABEL: test_vmov_double_imm:
+; CHECK-XO-DOUBLE-BE: movs [[REG:r[0-9]+]], #0
+; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
+; CHECK-XO-DOUBLE-NOT: vldr
   ret double 0.0
 }
 
@@ -53,6 +101,19 @@ define arm_aapcs_vfpcc double @test_vmvn
 
 ; CHECK-NONEON-LABEL: test_vmvn_double_imm:
 ; CHECK-NONEON: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-NO-XO-LABEL: test_vmvn_double_imm:
+; CHECK-NO-XO: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-DOUBLE-LABEL: test_vmvn_double_imm:
+; CHECK-XO-DOUBLE: mvn [[REG:r[0-9]+]], #-1342177280
+; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
+; CHECK-XO-DOUBLE-NOT: vldr
+
+; CHECK-XO-DOUBLE-BE-LABEL: test_vmvn_double_imm:
+; CHECK-XO-DOUBLE-BE: mvn [[REG:r[0-9]+]], #-1342177280
+; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
+; CHECK-XO-DOUBLE-BE-NOT: vldr
   ret double 0x4fffffff4fffffff
 }
 
@@ -64,5 +125,54 @@ define arm_aapcs_vfpcc double @test_notv
 
 ; CHECK-NONEON-LABEL: test_notvmvn_double_imm:
 ; CHECK-NONEON: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-NO-XO-LABEL: test_notvmvn_double_imm:
+; CHECK-NO-XO: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-DOUBLE-LABEL: test_notvmvn_double_imm:
+; CHECK-XO-DOUBLE: mvn [[REG1:r[0-9]+]], #-1342177280
+; CHECK-XO-DOUBLE: mov.w [[REG2:r[0-9]+]], #-1
+; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
+; CHECK-XO-DOUBLE-NOT: vldr
+
+; CHECK-XO-DOUBLE-BE-LABEL: test_notvmvn_double_imm:
+; CHECK-XO-DOUBLE-BE: mov.w [[REG1:r[0-9]+]], #-1
+; CHECK-XO-DOUBLE-BE: mvn [[REG2:r[0-9]+]], #-1342177280
+; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
+; CHECK-XO-DOUBLE-BE-NOT: vldr
   ret double 0x4fffffffffffffff
 }
+
+define arm_aapcs_vfpcc float @lower_const_f32_xo() {
+; CHECK-NO-XO-LABEL: lower_const_f32_xo
+; CHECK-NO-XO: vldr {{s[0-9]+}}, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-FLOAT-LABEL: lower_const_f32_xo
+; CHECK-XO-FLOAT: movw [[REG:r[0-9]+]], #29884
+; CHECK-XO-FLOAT: movt [[REG]], #16083
+; CHECK-XO-FLOAT: vmov {{s[0-9]+}}, [[REG]]
+; CHECK-XO-FLOAT-NOT: vldr
+  ret float 0x3FDA6E9780000000
+}
+
+define arm_aapcs_vfpcc double @lower_const_f64_xo() {
+; CHECK-NO-XO-LABEL: lower_const_f64_xo
+; CHECK-NO-XO: vldr {{d[0-9]+}}, {{.?LCPI[0-9]+_[0-9]+}}
+
+; CHECK-XO-DOUBLE-LABEL: lower_const_f64_xo
+; CHECK-XO-DOUBLE: movw [[REG1:r[0-9]+]], #6291
+; CHECK-XO-DOUBLE: movw [[REG2:r[0-9]+]], #27263
+; CHECK-XO-DOUBLE: movt [[REG1]], #16340
+; CHECK-XO-DOUBLE: movt [[REG2]], #29884
+; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
+; CHECK-XO-DOUBLE-NOT: vldr
+
+; CHECK-XO-DOUBLE-BE-LABEL: lower_const_f64_xo
+; CHECK-XO-DOUBLE-BE: movw [[REG1:r[0-9]+]], #27263
+; CHECK-XO-DOUBLE-BE: movw [[REG2:r[0-9]+]], #6291
+; CHECK-XO-DOUBLE-BE: movt [[REG1]], #29884
+; CHECK-XO-DOUBLE-BE: movt [[REG2]], #16340
+; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
+; CHECK-XO-DOUBLE-BE-NOT: vldr
+  ret double 3.140000e-01
+}

Added: llvm/trunk/test/CodeGen/ARM/execute-only-big-stack-frame.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/execute-only-big-stack-frame.ll?rev=289784&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/execute-only-big-stack-frame.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/execute-only-big-stack-frame.ll Thu Dec 15 01:59:08 2016
@@ -0,0 +1,46 @@
+; RUN: llc < %s -mtriple=thumbv7m -arm-execute-only -O0 %s -o - \
+; RUN:  | FileCheck --check-prefix=CHECK-SUBW-ADDW %s
+; RUN: llc < %s -mtriple=thumbv8m.base -arm-execute-only -O0 %s -o - \
+; RUN:  | FileCheck --check-prefix=CHECK-MOVW-MOVT-ADD %s
+; RUN: llc < %s -mtriple=thumbv8m.main -arm-execute-only -O0 %s -o - \
+; RUN:  | FileCheck --check-prefix=CHECK-SUBW-ADDW %s
+
+define i8 @test_big_stack_frame() {
+; CHECK-SUBW-ADDW-LABEL: test_big_stack_frame:
+; CHECK-SUBW-ADDW-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-SUBW-ADDW:       sub.w sp, sp, #65536
+; CHECK-SUBW-ADDW-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-SUBW-ADDW:       add.w [[REG1:r[0-9]+]], sp, #255
+; CHECK-SUBW-ADDW:       add.w {{r[0-9]+}}, [[REG1]], #65280
+; CHECK-SUBW-ADDW-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-SUBW-ADDW:       add.w lr, sp, #61440
+; CHECK-SUBW-ADDW-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-SUBW-ADDW:       add.w sp, sp, #65536
+
+; CHECK-MOVW-MOVT-ADD-LABEL: test_big_stack_frame:
+; CHECK-MOVW-MOVT-ADD-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-MOVW-MOVT-ADD:       movw [[REG1:r[0-9]+]], #0
+; CHECK-MOVW-MOVT-ADD:       movt [[REG1]], #65535
+; CHECK-MOVW-MOVT-ADD:       add sp, [[REG1]]
+; CHECK-MOVW-MOVT-ADD-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-MOVW-MOVT-ADD:       movw [[REG2:r[0-9]+]], #65532
+; CHECK-MOVW-MOVT-ADD:       movt [[REG2]], #0
+; CHECK-MOVW-MOVT-ADD:       add [[REG2]], sp
+; CHECK-MOVW-MOVT-ADD-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-MOVW-MOVT-ADD:       movw [[REG3:r[0-9]+]], #65532
+; CHECK-MOVW-MOVT-ADD:       movt [[REG3]], #0
+; CHECK-MOVW-MOVT-ADD:       add [[REG3]], sp
+; CHECK-MOVW-MOVT-ADD-NOT:   ldr {{r[0-9]+}}, .{{.*}}
+; CHECK-MOVW-MOVT-ADD:       movw [[REG4:r[0-9]+]], #0
+; CHECK-MOVW-MOVT-ADD:       movt [[REG4]], #1
+; CHECK-MOVW-MOVT-ADD:       add sp, [[REG4]]
+
+entry:
+  %s1 = alloca i8
+  %buffer = alloca [65528 x i8], align 1
+  call void @foo(i8* %s1)
+  %load = load i8, i8* %s1
+  ret i8 %load
+}
+
+declare void @foo(i8*)

Added: llvm/trunk/test/CodeGen/ARM/execute-only-section.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/execute-only-section.ll?rev=289784&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/execute-only-section.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/execute-only-section.ll Thu Dec 15 01:59:08 2016
@@ -0,0 +1,23 @@
+; RUN: llc < %s -mtriple=thumbv7m -arm-execute-only %s -o - | FileCheck %s
+; RUN: llc < %s -mtriple=thumbv8m.base -arm-execute-only %s -o - | FileCheck %s
+; RUN: llc < %s -mtriple=thumbv8m.main -arm-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
+}

Added: llvm/trunk/test/CodeGen/ARM/execute-only.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/execute-only.ll?rev=289784&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/execute-only.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/execute-only.ll Thu Dec 15 01:59:08 2016
@@ -0,0 +1,82 @@
+; RUN: llc -mtriple=thumbv8m.base-eabi -arm-execute-only %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-T2BASE %s
+; RUN: llc -mtriple=thumbv7m-eabi      -arm-execute-only %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-T2 %s
+; RUN: llc -mtriple=thumbv8m.main-eabi -arm-execute-only %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-T2 %s
+
+ at var = global i32 0
+
+define i32 @global() minsize {
+; CHECK-LABEL: global:
+; CHECK: movw [[GLOBDEST:r[0-9]+]], :lower16:var
+; CHECK: movt [[GLOBDEST]], :upper16:var
+
+  %val = load i32, i32* @var
+  ret i32 %val
+}
+
+define i32 @jump_table(i32 %c, i32 %a, i32 %b) #0 {
+; CHECK-LABEL: jump_table:
+; CHECK-T2: adr.w   [[REG_JT:r[0-9]+]], .LJTI1_0
+; CHECK-T2: add.w   [[REG_ENTRY:r[0-9]+]], [[REG_JT]], {{r[0-9]+}}, lsl #2
+; CHECK-T2: mov     pc, [[REG_ENTRY]]
+
+; CHECK-T2BASE: lsls    [[REG_OFFSET:r[0-9]+]], {{r[0-9]+}}, #2
+; CHECK-T2BASE: adr     [[REG_JT:r[0-9]+]], .LJTI1_0
+; CHECK-T2BASE: adds    [[REG_ENTRY:r[0-9]+]], [[REG_OFFSET]], [[REG_JT]]
+; CHECK-T2BASE: mov     pc, [[REG_ENTRY]]
+
+; CHECK-LABEL: .LJTI1_0:
+; CHECK-NEXT: b.w
+; CHECK-NEXT: b.w
+; CHECK-NEXT: b.w
+; CHECK-NEXT: b.w
+; CHECK-NEXT: b.w
+; CHECK-NEXT: b.w
+
+entry:
+  switch i32 %c, label %return [
+    i32 1, label %sw.bb
+    i32 2, label %sw.bb1
+    i32 3, label %sw.bb3
+    i32 4, label %sw.bb4
+    i32 5, label %sw.bb6
+    i32 6, label %sw.bb8
+  ]
+
+sw.bb:                                            ; preds = %entry
+  %add = add nsw i32 %a, 6
+  br label %return
+
+sw.bb1:                                           ; preds = %entry
+  %add2 = add nsw i32 %a, 4
+  br label %return
+
+sw.bb3:                                           ; preds = %entry
+  %sub = add nsw i32 %a, -3
+  br label %return
+
+sw.bb4:                                           ; preds = %entry
+  %add5 = add nsw i32 %b, 5
+  br label %return
+
+sw.bb6:                                           ; preds = %entry
+  %add7 = add nsw i32 %a, 1
+  br label %return
+
+sw.bb8:                                           ; preds = %entry
+  %add9 = add nsw i32 %a, 2
+  br label %return
+
+return:                                           ; preds = %entry, %sw.bb8, %sw.bb6, %sw.bb4, %sw.bb3, %sw.bb1, %sw.bb
+  %retval.0 = phi i32 [ %add9, %sw.bb8 ], [ %add7, %sw.bb6 ], [ %add5, %sw.bb4 ], [ %sub, %sw.bb3 ], [ %add2, %sw.bb1 ], [ %add, %sw.bb ], [ 0, %entry ]
+  ret i32 %retval.0
+}
+
+ at .str = private unnamed_addr constant [4 x i8] c"FOO\00", align 1
+
+define hidden i8* @string_literal() {
+entry:
+; CHECK-LABEL: string_literal:
+; CHECK-NOT: .asciz
+; CHECK: .fnend
+    ret i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)
+}

Added: llvm/trunk/test/MC/ELF/ARM/execute-only-section.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/ARM/execute-only-section.s?rev=289784&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/ARM/execute-only-section.s (added)
+++ llvm/trunk/test/MC/ELF/ARM/execute-only-section.s Thu Dec 15 01:59:08 2016
@@ -0,0 +1,44 @@
+// RUN: llvm-mc -filetype=obj -triple thumbv7m-arm-linux-gnu %s -o - \
+// RUN: | llvm-readobj -s -t | FileCheck %s
+
+        .section        .text,"axy",%progbits,unique,0
+        .globl  foo
+        .align  2
+        .type   foo,%function
+        .code   16
+        .thumb_func
+foo:
+        .fnstart
+        bx      lr
+.Lfunc_end0:
+        .size   foo, .Lfunc_end0-foo
+        .fnend
+
+        .section        ".note.GNU-stack","",%progbits
+
+
+// CHECK:      Section {
+// CHECK:        Name: .text (16)
+// CHECK-NEXT:   Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT:   Flags [ (0x6)
+// CHECK-NEXT:     SHF_ALLOC (0x2)
+// CHECK-NEXT:     SHF_EXECINSTR (0x4)
+// CHECK-NEXT:   ]
+// CHECK:        Size: 0
+// CHECK:      }
+
+// CHECK:      Section {
+// CHECK:        Name: .text (16)
+// CHECK-NEXT:   Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT:   Flags [ (0x20000006)
+// CHECK-NEXT:     SHF_ALLOC (0x2)
+// CHECK-NEXT:     SHF_ARM_PURECODE (0x20000000)
+// CHECK-NEXT:     SHF_EXECINSTR (0x4)
+// CHECK-NEXT:   ]
+// CHECK:        Size: 2
+// CHECK:      }
+
+// CHECK: Symbol {
+// CHECK:   Name: foo (22)
+// CHECK:   Section: .text (0x3)
+// CHECK: }

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=289784&r1=289783&r2=289784&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Thu Dec 15 01:59:08 2016
@@ -1069,6 +1069,10 @@ static const EnumEntry<unsigned> ElfAMDG
   LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT)
 };
 
+static const EnumEntry<unsigned> ElfARMSectionFlags[] = {
+  LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE)
+};
+
 static const EnumEntry<unsigned> ElfHexagonSectionFlags[] = {
   LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL)
 };
@@ -3596,6 +3600,10 @@ template <class ELFT> void LLVMStyle<ELF
       SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags),
                           std::end(ElfAMDGPUSectionFlags));
       break;
+    case EM_ARM:
+      SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags),
+                          std::end(ElfARMSectionFlags));
+      break;
     case EM_HEXAGON:
       SectionFlags.insert(SectionFlags.end(),
                           std::begin(ElfHexagonSectionFlags),




More information about the llvm-commits mailing list