llvm.org GIT mirror llvm / af672fb
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289784 91177308-0d34-0410-b5e6-96231b3b80d8 Prakhar Bahuguna 2 years ago
27 changed file(s) with 455 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
3232
3333 class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
3434 bool UseInitArray;
35 mutable unsigned NextUniqueID = 0;
35 mutable unsigned NextUniqueID = 1; // ID 0 is reserved for execute-only sections
3636
3737 protected:
3838 MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =
2727 /// Text - Text section, used for functions and other executable code.
2828 Text,
2929
30 /// ExecuteOnly, Text section that is not readable.
31 ExecuteOnly,
32
3033 /// ReadOnly - Data that is never written to at program runtime by the
3134 /// program or the dynamic linker. Things in the top-level readonly
3235 /// SectionKind are not mergeable.
111114 public:
112115
113116 bool isMetadata() const { return K == Metadata; }
114 bool isText() const { return K == Text; }
117
118 bool isText() const { return K == Text || K == ExecuteOnly; }
119
120 bool isExecuteOnly() const { return K == ExecuteOnly; }
115121
116122 bool isReadOnly() const {
117123 return K == ReadOnly || isMergeableCString() ||
171177
172178 static SectionKind getMetadata() { return get(Metadata); }
173179 static SectionKind getText() { return get(Text); }
180 static SectionKind getExecuteOnly() { return get(ExecuteOnly); }
174181 static SectionKind getReadOnly() { return get(ReadOnly); }
175182 static SectionKind getMergeable1ByteCString() {
176183 return get(Mergeable1ByteCString);
803803 // Section data is string data by default.
804804 SHF_MIPS_STRING = 0x80000000,
805805
806 // Make code section unreadable when in execute-only mode
807 SHF_ARM_PURECODE = 0x20000000,
808
806809 SHF_AMDGPU_HSA_GLOBAL = 0x00100000,
807810 SHF_AMDGPU_HSA_READONLY = 0x00200000,
808811 SHF_AMDGPU_HSA_CODE = 0x00400000,
180180 if (K.isText())
181181 Flags |= ELF::SHF_EXECINSTR;
182182
183 if (K.isExecuteOnly())
184 Flags |= ELF::SHF_ARM_PURECODE;
185
183186 if (K.isWriteable())
184187 Flags |= ELF::SHF_WRITE;
185188
311314 UniqueID = *NextUniqueID;
312315 (*NextUniqueID)++;
313316 }
317 // Use 0 as the unique ID for execute-only text
318 if (Kind.isExecuteOnly())
319 UniqueID = 0;
314320 return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
315321 EntrySize, Group, UniqueID);
316322 }
367367 StringRef CachedName = Entry.first.SectionName;
368368
369369 SectionKind Kind;
370 if (Flags & ELF::SHF_EXECINSTR)
370 if (Flags & ELF::SHF_ARM_PURECODE)
371 Kind = SectionKind::getExecuteOnly();
372 else if (Flags & ELF::SHF_EXECINSTR)
371373 Kind = SectionKind::getText();
372374 else
373375 Kind = SectionKind::getReadOnly();
292292 case 'd':
293293 flags |= ELF::XCORE_SHF_DP_SECTION;
294294 break;
295 case 'y':
296 flags |= ELF::SHF_ARM_PURECODE;
297 break;
295298 case 'G':
296299 flags |= ELF::SHF_GROUP;
297300 break;
109109 OS << 'c';
110110 if (Flags & ELF::XCORE_SHF_DP_SECTION)
111111 OS << 'd';
112 if (Flags & ELF::SHF_ARM_PURECODE)
113 OS << 'y';
112114
113115 OS << '"';
114116
422422 BCase(SHF_GROUP)
423423 BCase(SHF_TLS)
424424 switch(Object->Header.Machine) {
425 case ELF::EM_ARM:
426 BCase(SHF_ARM_PURECODE)
427 break;
425428 case ELF::EM_AMDGPU:
426429 BCase(SHF_AMDGPU_HSA_GLOBAL)
427430 BCase(SHF_AMDGPU_HSA_READONLY)
231231 break;
232232 }
233233 case MachineOperand::MO_ConstantPoolIndex:
234 if (Subtarget->genExecuteOnly())
235 llvm_unreachable("execute-only should not generate constant pools");
234236 GetCPISymbol(MO.getIndex())->print(O, MAI);
235237 break;
236238 }
422422 MadeChange |= optimizeThumb2Branches();
423423
424424 // Optimize jump tables using TBB / TBH.
425 if (GenerateTBB)
425 if (GenerateTBB && !STI->genExecuteOnly())
426426 MadeChange |= optimizeThumb2JumpTables();
427427
428428 // After a while, this might be made debug-only, but it is not expensive.
31513151 (isa(GV) && cast(GV)->isConstant()) ||
31523152 isa(GV);
31533153
3154 if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
3154 // promoteToConstantPool only if not generating XO text section
3155 if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV) && !Subtarget->genExecuteOnly())
31553156 if (SDValue V = promoteToConstantPool(GV, DAG, PtrVT, dl))
31563157 return V;
31573158
44914492 Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
44924493 Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, dl, PTy));
44934494 SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table);
4494 if (Subtarget->isThumb2()) {
4495 // Thumb2 uses a two-level jump. That is, it jumps into the jump table
4495 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
4496 // Thumb2 and ARMv8-M use a two-level jump. That is, it jumps into the jump table
44964497 // which does another jump to the destination. This also makes it easier
4497 // to translate it to TBB / TBH later.
4498 // to translate it to TBB / TBH later (Thumb2 only).
44984499 // FIXME: This might not work if the function is extremely large.
44994500 return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
45004501 Addr, Op.getOperand(2), JTI);
55705571
55715572 SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG,
55725573 const ARMSubtarget *ST) const {
5574 bool IsDouble = Op.getValueType() == MVT::f64;
5575 ConstantFPSDNode *CFP = cast(Op);
5576 const APFloat &FPVal = CFP->getValueAPF();
5577
5578 // Prevent floating-point constants from using literal loads
5579 // when execute-only is enabled.
5580 if (ST->genExecuteOnly()) {
5581 APInt INTVal = FPVal.bitcastToAPInt();
5582 SDLoc DL(CFP);
5583 if (IsDouble) {
5584 SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32);
5585 SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32);
5586 if (!ST->isLittle())
5587 std::swap(Lo, Hi);
5588 return DAG.getNode(ARMISD::VMOVDRR, DL, MVT::f64, Lo, Hi);
5589 } else {
5590 return DAG.getConstant(INTVal, DL, MVT::i32);
5591 }
5592 }
5593
55735594 if (!ST->hasVFP3())
55745595 return SDValue();
5575
5576 bool IsDouble = Op.getValueType() == MVT::f64;
5577 ConstantFPSDNode *CFP = cast(Op);
55785596
55795597 // Use the default (constant pool) lowering for double constants when we have
55805598 // an SP-only FPU
55825600 return SDValue();
55835601
55845602 // Try splatting with a VMOV.f32...
5585 const APFloat &FPVal = CFP->getValueAPF();
55865603 int ImmVal = IsDouble ? ARM_AM::getFP64Imm(FPVal) : ARM_AM::getFP32Imm(FPVal);
55875604
55885605 if (ImmVal != -1) {
76167633 switch (Op.getOpcode()) {
76177634 default: llvm_unreachable("Don't know how to custom lower this!");
76187635 case ISD::WRITE_REGISTER: return LowerWRITE_REGISTER(Op, DAG);
7619 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
7636 case ISD::ConstantPool:
7637 if (Subtarget->genExecuteOnly())
7638 llvm_unreachable("execute-only should not generate constant pools");
7639 return LowerConstantPool(Op, DAG);
76207640 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
76217641 case ISD::GlobalAddress:
76227642 switch (Subtarget->getTargetTriple().getObjectFormat()) {
395395 : PseudoInst {
396396 let Size = sz;
397397 list Predicates = [IsThumb];
398 }
399
400 // PseudoInst that's in ARMv8-M baseline (Somewhere between Thumb and Thumb2)
401 class t2basePseudoInst
402 list pattern>
403 : PseudoInst {
404 let Size = sz;
405 list Predicates = [IsThumb,HasV8MBaseline];
398406 }
399407
400408 // PseudoInst that's Thumb2-mode only.
329329 def IsLE : Predicate<"MF->getDataLayout().isLittleEndian()">;
330330 def IsBE : Predicate<"MF->getDataLayout().isBigEndian()">;
331331
332 def GenExecuteOnly : Predicate<"Subtarget->genExecuteOnly()">;
333
332334 //===----------------------------------------------------------------------===//
333335 // ARM Flag Definitions.
334336
33803380 }
33813381
33823382 let Size = 4, isNotDuplicable = 1, isIndirectBranch = 1 in {
3383 def t2BR_JT : t2PseudoInst<(outs),
3383
3384 // available in both v8-M.Baseline and Thumb2 targets
3385 def t2BR_JT : t2basePseudoInst<(outs),
33843386 (ins GPR:$target, GPR:$index, i32imm:$jt),
33853387 0, IIC_Br,
33863388 [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt)]>,
9090 MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
9191 break;
9292 case MachineOperand::MO_ConstantPoolIndex:
93 if (Subtarget->genExecuteOnly())
94 llvm_unreachable("execute-only should not generate constant pools");
9395 MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
9496 break;
9597 case MachineOperand::MO_BlockAddress:
7575 return *this;
7676 }
7777
78 /// EnableExecuteOnly - Enables the generation of execute-only code on supported
79 /// targets
80 static cl::opt
81 EnableExecuteOnly("arm-execute-only");
82
7883 ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
7984 StringRef FS) {
8085 ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
8994 const ARMBaseTargetMachine &TM, bool IsLittle)
9095 : ARMGenSubtargetInfo(TT, CPU, FS), UseMulOps(UseFusedMulOps),
9196 CPUString(CPU), IsLittle(IsLittle), TargetTriple(TT), Options(TM.Options),
92 TM(TM), FrameLowering(initializeFrameLowering(CPU, FS)),
97 TM(TM), GenExecuteOnly(EnableExecuteOnly),
98 FrameLowering(initializeFrameLowering(CPU, FS)),
9399 // At this point initializeSubtargetDependencies has been called so
94100 // we can query directly.
95101 InstrInfo(isThumb1Only()
167173 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
168174 // Assert this for now to make the change obvious.
169175 assert(hasV6T2Ops() || !hasThumb2());
176
177 // Execute only support requires movt support
178 if (genExecuteOnly())
179 assert(hasV8MBaselineOps() && !NoMovt && "Cannot generate execute-only code for this target");
170180
171181 // Keep a pointer to static instruction cost data for the specified CPU.
172182 SchedModel = getSchedModelForCPU(CPUString);
352362 // immediates as it is inherently position independent, and may be out of
353363 // range otherwise.
354364 return !NoMovt && hasV8MBaselineOps() &&
355 (isTargetWindows() || !MF.getFunction()->optForMinSize());
365 (isTargetWindows() || !MF.getFunction()->optForMinSize() || genExecuteOnly());
356366 }
357367
358368 bool ARMSubtarget::useFastISel() const {
299299
300300 /// Generate calls via indirect call instructions.
301301 bool GenLongCalls = false;
302
303 /// Generate code that does not contain data access to code sections.
304 bool GenExecuteOnly = false;
302305
303306 /// Target machine allowed unsafe FP math (such as use of NEON fp)
304307 bool UnsafeFPMath = false;
493496 bool useNaClTrap() const { return UseNaClTrap; }
494497 bool useSjLjEH() const { return UseSjLjEH; }
495498 bool genLongCalls() const { return GenLongCalls; }
499 bool genExecuteOnly() const { return GenExecuteOnly; }
496500
497501 bool hasFP16() const { return HasFP16; }
498502 bool hasD16() const { return HasD16; }
2626
2727 void ARMElfTargetObjectFile::Initialize(MCContext &Ctx,
2828 const TargetMachine &TM) {
29 bool isAAPCS_ABI = static_cast(TM).TargetABI ==
30 ARMTargetMachine::ARMABI::ARM_ABI_AAPCS;
29 const ARMTargetMachine &ARM_TM = static_cast(TM);
30 bool isAAPCS_ABI = ARM_TM.TargetABI == ARMTargetMachine::ARMABI::ARM_ABI_AAPCS;
31 genExecuteOnly = ARM_TM.getSubtargetImpl()->genExecuteOnly();
32
3133 TargetLoweringObjectFileELF::Initialize(Ctx, TM);
3234 InitializeELF(isAAPCS_ABI);
3335
3739
3840 AttributesSection =
3941 getContext().getELFSection(".ARM.attributes", ELF::SHT_ARM_ATTRIBUTES, 0);
42
43 // Make code section unreadable when in execute-only mode
44 if (genExecuteOnly) {
45 unsigned Type = ELF::SHT_PROGBITS;
46 unsigned Flags = ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_ARM_PURECODE;
47 // Since we cannot modify flags for an existing section, we create a new
48 // section with the right flags, and use 0 as the unique ID for
49 // execute-only text
50 TextSection = Ctx.getELFSection(".text", Type, Flags, 0, "", 0U);
51 }
4052 }
4153
4254 const MCExpr *ARMElfTargetObjectFile::getTTypeGlobalReference(
5769 return MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_ARM_TLSLDO,
5870 getContext());
5971 }
72
73 MCSection *
74 ARMElfTargetObjectFile::getExplicitSectionGlobal(const GlobalObject *GO,
75 SectionKind SK, const TargetMachine &TM) const {
76 // Set execute-only access for the explicit section
77 if (genExecuteOnly && SK.isText())
78 SK = SectionKind::getExecuteOnly();
79
80 return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GO, SK, TM);
81 }
82
83 MCSection *
84 ARMElfTargetObjectFile::SelectSectionForGlobal(const GlobalObject *GO,
85 SectionKind SK, const TargetMachine &TM) const {
86 // Place the global in the execute-only text section
87 if (genExecuteOnly && SK.isText())
88 SK = SectionKind::getExecuteOnly();
89
90 return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, SK, TM);
91 }
1717 class TargetMachine;
1818
1919 class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
20 mutable bool genExecuteOnly = false;
2021 protected:
2122 const MCSection *AttributesSection;
2223 public:
3536
3637 /// \brief Describe a TLS variable address within debug info.
3738 const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override;
39
40 MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
41 const TargetMachine &TM) const override;
42
43 MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
44 const TargetMachine &TM) const override;
3845 };
3946
4047 } // end namespace llvm
54525452 if (getParser().parseExpression(SubExprVal))
54535453 return true;
54545454 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5455
5456 // execute-only: we assume that assembly programmers know what they are
5457 // doing and allow literal pool creation here
54555458 Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E));
54565459 return false;
54575460 }
125125 bool CanChangeCC, const TargetInstrInfo &TII,
126126 const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) {
127127 MachineFunction &MF = *MBB.getParent();
128 const ARMSubtarget &ST = MF.getSubtarget();
128129 bool isHigh = !isARMLowRegister(DestReg) ||
129130 (BaseReg != 0 && !isARMLowRegister(BaseReg));
130131 bool isSub = false;
153154 AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
154155 .addReg(LdReg, RegState::Kill)
155156 .setMIFlags(MIFlags);
157 } else if (ST.genExecuteOnly()) {
158 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), LdReg)
159 .addImm(NumBytes).setMIFlags(MIFlags);
156160 } else
157161 MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0,
158162 MIFlags);
569573 unsigned TmpReg = MI.getOperand(0).getReg();
570574 bool UseRR = false;
571575 if (Opcode == ARM::tLDRspi) {
572 if (FrameReg == ARM::SP)
576 if (FrameReg == ARM::SP || STI.genExecuteOnly())
573577 emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
574578 Offset, false, TII, *this);
575579 else {
593597 bool UseRR = false;
594598
595599 if (Opcode == ARM::tSTRspi) {
596 if (FrameReg == ARM::SP)
600 if (FrameReg == ARM::SP || STI.genExecuteOnly())
597601 emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
598602 Offset, false, TII, *this);
599603 else {
0 ; RUN: llc -mtriple=armv7 -mattr=+neon -mcpu=swift %s -o - | FileCheck %s
11 ; RUN: llc -mtriple=armv7 -mattr=+neon -mcpu=cortex-a8 %s -o - | FileCheck --check-prefix=CHECK-NONEONFP %s
22 ; RUN: llc -mtriple=armv7 -mattr=-neon -mcpu=cortex-a8 %s -o - | FileCheck --check-prefix=CHECK-NONEON %s
3
4 ; RUN: llc -mtriple=thumbv7m -mcpu=cortex-m4 %s -o - \
5 ; RUN: | FileCheck --check-prefix=CHECK-NO-XO %s
6
7 ; RUN: llc -mtriple=thumbv7m -arm-execute-only -mcpu=cortex-m4 %s -o - \
8 ; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE %s
9
10 ; RUN: llc -mtriple=thumbv7meb -arm-execute-only -mcpu=cortex-m4 %s -o - \
11 ; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE-BE %s
12
13 ; RUN: llc -mtriple=thumbv8m.main -mattr=fp-armv8 %s -o - \
14 ; RUN: | FileCheck --check-prefix=CHECK-NO-XO %s
15
16 ; RUN: llc -mtriple=thumbv8m.main -arm-execute-only -mattr=fp-armv8 %s -o - \
17 ; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE %s
18
19 ; RUN: llc -mtriple=thumbv8m.maineb -arm-execute-only -mattr=fp-armv8 %s -o - \
20 ; RUN: | FileCheck --check-prefix=CHECK-XO-FLOAT --check-prefix=CHECK-XO-DOUBLE-BE %s
21
322
423 define arm_aapcs_vfpcc float @test_vmov_f32() {
524 ; CHECK-LABEL: test_vmov_f32:
1534
1635 ; CHECK-NONEON-LABEL: test_vmov_imm:
1736 ; CHECK-NONEON: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
37
38 ; CHECK-NO-XO-LABEL: test_vmov_imm:
39 ; CHECK-NO-XO: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
40
41 ; CHECK-XO-FLOAT-LABEL: test_vmov_imm:
42 ; CHECK-XO-FLOAT: movs [[REG:r[0-9]+]], #0
43 ; CHECK-XO-FLOAT: vmov {{s[0-9]+}}, [[REG]]
44 ; CHECK-XO-FLOAT-NOT: vldr
1845 ret float 0.0
1946 }
2047
2451
2552 ; CHECK-NONEON-LABEL: test_vmvn_imm:
2653 ; CHECK-NONEON: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
54
55 ; CHECK-NO-XO-LABEL: test_vmvn_imm:
56 ; CHECK-NO-XO: vldr s0, {{.?LCPI[0-9]+_[0-9]+}}
57
58 ; CHECK-XO-FLOAT-LABEL: test_vmvn_imm:
59 ; CHECK-XO-FLOAT: mvn [[REG:r[0-9]+]], #-1342177280
60 ; CHECK-XO-FLOAT: vmov {{s[0-9]+}}, [[REG]]
61 ; CHECK-XO-FLOAT-NOT: vldr
2762 ret float 8589934080.0
2863 }
2964
4378
4479 ; CHECK-NONEON-LABEL: test_vmov_double_imm:
4580 ; CHECK-NONEON: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
81
82 ; CHECK-NO-XO-LABEL: test_vmov_double_imm:
83 ; CHECK-NO-XO: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
84
85 ; CHECK-XO-DOUBLE-LABEL: test_vmov_double_imm:
86 ; CHECK-XO-DOUBLE: movs [[REG:r[0-9]+]], #0
87 ; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
88 ; CHECK-XO-DOUBLE-NOT: vldr
89
90 ; CHECK-XO-DOUBLE-BE-LABEL: test_vmov_double_imm:
91 ; CHECK-XO-DOUBLE-BE: movs [[REG:r[0-9]+]], #0
92 ; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
93 ; CHECK-XO-DOUBLE-NOT: vldr
4694 ret double 0.0
4795 }
4896
52100
53101 ; CHECK-NONEON-LABEL: test_vmvn_double_imm:
54102 ; CHECK-NONEON: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
103
104 ; CHECK-NO-XO-LABEL: test_vmvn_double_imm:
105 ; CHECK-NO-XO: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
106
107 ; CHECK-XO-DOUBLE-LABEL: test_vmvn_double_imm:
108 ; CHECK-XO-DOUBLE: mvn [[REG:r[0-9]+]], #-1342177280
109 ; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
110 ; CHECK-XO-DOUBLE-NOT: vldr
111
112 ; CHECK-XO-DOUBLE-BE-LABEL: test_vmvn_double_imm:
113 ; CHECK-XO-DOUBLE-BE: mvn [[REG:r[0-9]+]], #-1342177280
114 ; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG]], [[REG]]
115 ; CHECK-XO-DOUBLE-BE-NOT: vldr
55116 ret double 0x4fffffff4fffffff
56117 }
57118
63124
64125 ; CHECK-NONEON-LABEL: test_notvmvn_double_imm:
65126 ; CHECK-NONEON: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
127
128 ; CHECK-NO-XO-LABEL: test_notvmvn_double_imm:
129 ; CHECK-NO-XO: vldr d0, {{.?LCPI[0-9]+_[0-9]+}}
130
131 ; CHECK-XO-DOUBLE-LABEL: test_notvmvn_double_imm:
132 ; CHECK-XO-DOUBLE: mvn [[REG1:r[0-9]+]], #-1342177280
133 ; CHECK-XO-DOUBLE: mov.w [[REG2:r[0-9]+]], #-1
134 ; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
135 ; CHECK-XO-DOUBLE-NOT: vldr
136
137 ; CHECK-XO-DOUBLE-BE-LABEL: test_notvmvn_double_imm:
138 ; CHECK-XO-DOUBLE-BE: mov.w [[REG1:r[0-9]+]], #-1
139 ; CHECK-XO-DOUBLE-BE: mvn [[REG2:r[0-9]+]], #-1342177280
140 ; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
141 ; CHECK-XO-DOUBLE-BE-NOT: vldr
66142 ret double 0x4fffffffffffffff
67143 }
144
145 define arm_aapcs_vfpcc float @lower_const_f32_xo() {
146 ; CHECK-NO-XO-LABEL: lower_const_f32_xo
147 ; CHECK-NO-XO: vldr {{s[0-9]+}}, {{.?LCPI[0-9]+_[0-9]+}}
148
149 ; CHECK-XO-FLOAT-LABEL: lower_const_f32_xo
150 ; CHECK-XO-FLOAT: movw [[REG:r[0-9]+]], #29884
151 ; CHECK-XO-FLOAT: movt [[REG]], #16083
152 ; CHECK-XO-FLOAT: vmov {{s[0-9]+}}, [[REG]]
153 ; CHECK-XO-FLOAT-NOT: vldr
154 ret float 0x3FDA6E9780000000
155 }
156
157 define arm_aapcs_vfpcc double @lower_const_f64_xo() {
158 ; CHECK-NO-XO-LABEL: lower_const_f64_xo
159 ; CHECK-NO-XO: vldr {{d[0-9]+}}, {{.?LCPI[0-9]+_[0-9]+}}
160
161 ; CHECK-XO-DOUBLE-LABEL: lower_const_f64_xo
162 ; CHECK-XO-DOUBLE: movw [[REG1:r[0-9]+]], #6291
163 ; CHECK-XO-DOUBLE: movw [[REG2:r[0-9]+]], #27263
164 ; CHECK-XO-DOUBLE: movt [[REG1]], #16340
165 ; CHECK-XO-DOUBLE: movt [[REG2]], #29884
166 ; CHECK-XO-DOUBLE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
167 ; CHECK-XO-DOUBLE-NOT: vldr
168
169 ; CHECK-XO-DOUBLE-BE-LABEL: lower_const_f64_xo
170 ; CHECK-XO-DOUBLE-BE: movw [[REG1:r[0-9]+]], #27263
171 ; CHECK-XO-DOUBLE-BE: movw [[REG2:r[0-9]+]], #6291
172 ; CHECK-XO-DOUBLE-BE: movt [[REG1]], #29884
173 ; CHECK-XO-DOUBLE-BE: movt [[REG2]], #16340
174 ; CHECK-XO-DOUBLE-BE: vmov {{d[0-9]+}}, [[REG2]], [[REG1]]
175 ; CHECK-XO-DOUBLE-BE-NOT: vldr
176 ret double 3.140000e-01
177 }
0 ; RUN: llc < %s -mtriple=thumbv7m -arm-execute-only -O0 %s -o - \
1 ; RUN: | FileCheck --check-prefix=CHECK-SUBW-ADDW %s
2 ; RUN: llc < %s -mtriple=thumbv8m.base -arm-execute-only -O0 %s -o - \
3 ; RUN: | FileCheck --check-prefix=CHECK-MOVW-MOVT-ADD %s
4 ; RUN: llc < %s -mtriple=thumbv8m.main -arm-execute-only -O0 %s -o - \
5 ; RUN: | FileCheck --check-prefix=CHECK-SUBW-ADDW %s
6
7 define i8 @test_big_stack_frame() {
8 ; CHECK-SUBW-ADDW-LABEL: test_big_stack_frame:
9 ; CHECK-SUBW-ADDW-NOT: ldr {{r[0-9]+}}, .{{.*}}
10 ; CHECK-SUBW-ADDW: sub.w sp, sp, #65536
11 ; CHECK-SUBW-ADDW-NOT: ldr {{r[0-9]+}}, .{{.*}}
12 ; CHECK-SUBW-ADDW: add.w [[REG1:r[0-9]+]], sp, #255
13 ; CHECK-SUBW-ADDW: add.w {{r[0-9]+}}, [[REG1]], #65280
14 ; CHECK-SUBW-ADDW-NOT: ldr {{r[0-9]+}}, .{{.*}}
15 ; CHECK-SUBW-ADDW: add.w lr, sp, #61440
16 ; CHECK-SUBW-ADDW-NOT: ldr {{r[0-9]+}}, .{{.*}}
17 ; CHECK-SUBW-ADDW: add.w sp, sp, #65536
18
19 ; CHECK-MOVW-MOVT-ADD-LABEL: test_big_stack_frame:
20 ; CHECK-MOVW-MOVT-ADD-NOT: ldr {{r[0-9]+}}, .{{.*}}
21 ; CHECK-MOVW-MOVT-ADD: movw [[REG1:r[0-9]+]], #0
22 ; CHECK-MOVW-MOVT-ADD: movt [[REG1]], #65535
23 ; CHECK-MOVW-MOVT-ADD: add sp, [[REG1]]
24 ; CHECK-MOVW-MOVT-ADD-NOT: ldr {{r[0-9]+}}, .{{.*}}
25 ; CHECK-MOVW-MOVT-ADD: movw [[REG2:r[0-9]+]], #65532
26 ; CHECK-MOVW-MOVT-ADD: movt [[REG2]], #0
27 ; CHECK-MOVW-MOVT-ADD: add [[REG2]], sp
28 ; CHECK-MOVW-MOVT-ADD-NOT: ldr {{r[0-9]+}}, .{{.*}}
29 ; CHECK-MOVW-MOVT-ADD: movw [[REG3:r[0-9]+]], #65532
30 ; CHECK-MOVW-MOVT-ADD: movt [[REG3]], #0
31 ; CHECK-MOVW-MOVT-ADD: add [[REG3]], sp
32 ; CHECK-MOVW-MOVT-ADD-NOT: ldr {{r[0-9]+}}, .{{.*}}
33 ; CHECK-MOVW-MOVT-ADD: movw [[REG4:r[0-9]+]], #0
34 ; CHECK-MOVW-MOVT-ADD: movt [[REG4]], #1
35 ; CHECK-MOVW-MOVT-ADD: add sp, [[REG4]]
36
37 entry:
38 %s1 = alloca i8
39 %buffer = alloca [65528 x i8], align 1
40 call void @foo(i8* %s1)
41 %load = load i8, i8* %s1
42 ret i8 %load
43 }
44
45 declare void @foo(i8*)
0 ; RUN: llc < %s -mtriple=thumbv7m -arm-execute-only %s -o - | FileCheck %s
1 ; RUN: llc < %s -mtriple=thumbv8m.base -arm-execute-only %s -o - | FileCheck %s
2 ; RUN: llc < %s -mtriple=thumbv8m.main -arm-execute-only %s -o - | FileCheck %s
3
4 ; CHECK: .section .text,"axy",%progbits,unique,0
5 ; CHECK-NOT: .section
6 ; CHECK-NOT: .text
7 ; CHECK: .globl test_SectionForGlobal
8 ; CHECK: .type test_SectionForGlobal,%function
9 define void @test_SectionForGlobal() {
10 entry:
11 ret void
12 }
13
14 ; CHECK: .section .test,"axy",%progbits
15 ; CHECK-NOT: .section
16 ; CHECK-NOT: .text
17 ; CHECK: .globl test_ExplicitSectionForGlobal
18 ; CHECK: .type test_ExplicitSectionForGlobal,%function
19 define void @test_ExplicitSectionForGlobal() section ".test" {
20 entry:
21 ret void
22 }
0 ; RUN: llc -mtriple=thumbv8m.base-eabi -arm-execute-only %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-T2BASE %s
1 ; RUN: llc -mtriple=thumbv7m-eabi -arm-execute-only %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-T2 %s
2 ; RUN: llc -mtriple=thumbv8m.main-eabi -arm-execute-only %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-T2 %s
3
4 @var = global i32 0
5
6 define i32 @global() minsize {
7 ; CHECK-LABEL: global:
8 ; CHECK: movw [[GLOBDEST:r[0-9]+]], :lower16:var
9 ; CHECK: movt [[GLOBDEST]], :upper16:var
10
11 %val = load i32, i32* @var
12 ret i32 %val
13 }
14
15 define i32 @jump_table(i32 %c, i32 %a, i32 %b) #0 {
16 ; CHECK-LABEL: jump_table:
17 ; CHECK-T2: adr.w [[REG_JT:r[0-9]+]], .LJTI1_0
18 ; CHECK-T2: add.w [[REG_ENTRY:r[0-9]+]], [[REG_JT]], {{r[0-9]+}}, lsl #2
19 ; CHECK-T2: mov pc, [[REG_ENTRY]]
20
21 ; CHECK-T2BASE: lsls [[REG_OFFSET:r[0-9]+]], {{r[0-9]+}}, #2
22 ; CHECK-T2BASE: adr [[REG_JT:r[0-9]+]], .LJTI1_0
23 ; CHECK-T2BASE: adds [[REG_ENTRY:r[0-9]+]], [[REG_OFFSET]], [[REG_JT]]
24 ; CHECK-T2BASE: mov pc, [[REG_ENTRY]]
25
26 ; CHECK-LABEL: .LJTI1_0:
27 ; CHECK-NEXT: b.w
28 ; CHECK-NEXT: b.w
29 ; CHECK-NEXT: b.w
30 ; CHECK-NEXT: b.w
31 ; CHECK-NEXT: b.w
32 ; CHECK-NEXT: b.w
33
34 entry:
35 switch i32 %c, label %return [
36 i32 1, label %sw.bb
37 i32 2, label %sw.bb1
38 i32 3, label %sw.bb3
39 i32 4, label %sw.bb4
40 i32 5, label %sw.bb6
41 i32 6, label %sw.bb8
42 ]
43
44 sw.bb: ; preds = %entry
45 %add = add nsw i32 %a, 6
46 br label %return
47
48 sw.bb1: ; preds = %entry
49 %add2 = add nsw i32 %a, 4
50 br label %return
51
52 sw.bb3: ; preds = %entry
53 %sub = add nsw i32 %a, -3
54 br label %return
55
56 sw.bb4: ; preds = %entry
57 %add5 = add nsw i32 %b, 5
58 br label %return
59
60 sw.bb6: ; preds = %entry
61 %add7 = add nsw i32 %a, 1
62 br label %return
63
64 sw.bb8: ; preds = %entry
65 %add9 = add nsw i32 %a, 2
66 br label %return
67
68 return: ; preds = %entry, %sw.bb8, %sw.bb6, %sw.bb4, %sw.bb3, %sw.bb1, %sw.bb
69 %retval.0 = phi i32 [ %add9, %sw.bb8 ], [ %add7, %sw.bb6 ], [ %add5, %sw.bb4 ], [ %sub, %sw.bb3 ], [ %add2, %sw.bb1 ], [ %add, %sw.bb ], [ 0, %entry ]
70 ret i32 %retval.0
71 }
72
73 @.str = private unnamed_addr constant [4 x i8] c"FOO\00", align 1
74
75 define hidden i8* @string_literal() {
76 entry:
77 ; CHECK-LABEL: string_literal:
78 ; CHECK-NOT: .asciz
79 ; CHECK: .fnend
80 ret i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)
81 }
0 // RUN: llvm-mc -filetype=obj -triple thumbv7m-arm-linux-gnu %s -o - \
1 // RUN: | llvm-readobj -s -t | FileCheck %s
2
3 .section .text,"axy",%progbits,unique,0
4 .globl foo
5 .align 2
6 .type foo,%function
7 .code 16
8 .thumb_func
9 foo:
10 .fnstart
11 bx lr
12 .Lfunc_end0:
13 .size foo, .Lfunc_end0-foo
14 .fnend
15
16 .section ".note.GNU-stack","",%progbits
17
18
19 // CHECK: Section {
20 // CHECK: Name: .text (16)
21 // CHECK-NEXT: Type: SHT_PROGBITS (0x1)
22 // CHECK-NEXT: Flags [ (0x6)
23 // CHECK-NEXT: SHF_ALLOC (0x2)
24 // CHECK-NEXT: SHF_EXECINSTR (0x4)
25 // CHECK-NEXT: ]
26 // CHECK: Size: 0
27 // CHECK: }
28
29 // CHECK: Section {
30 // CHECK: Name: .text (16)
31 // CHECK-NEXT: Type: SHT_PROGBITS (0x1)
32 // CHECK-NEXT: Flags [ (0x20000006)
33 // CHECK-NEXT: SHF_ALLOC (0x2)
34 // CHECK-NEXT: SHF_ARM_PURECODE (0x20000000)
35 // CHECK-NEXT: SHF_EXECINSTR (0x4)
36 // CHECK-NEXT: ]
37 // CHECK: Size: 2
38 // CHECK: }
39
40 // CHECK: Symbol {
41 // CHECK: Name: foo (22)
42 // CHECK: Section: .text (0x3)
43 // CHECK: }
10681068 LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT)
10691069 };
10701070
1071 static const EnumEntry ElfARMSectionFlags[] = {
1072 LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE)
1073 };
1074
10711075 static const EnumEntry ElfHexagonSectionFlags[] = {
10721076 LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL)
10731077 };
35953599 SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags),
35963600 std::end(ElfAMDGPUSectionFlags));
35973601 break;
3602 case EM_ARM:
3603 SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags),
3604 std::end(ElfARMSectionFlags));
3605 break;
35983606 case EM_HEXAGON:
35993607 SectionFlags.insert(SectionFlags.end(),
36003608 std::begin(ElfHexagonSectionFlags),