mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-31 17:42:40 +00:00
[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
This commit is contained in:
parent
a1b0287fa3
commit
af672fb209
@ -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 =
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -181,6 +181,9 @@ static unsigned getELFSectionFlags(SectionKind K) {
|
||||
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, const GlobalObject *GO,
|
||||
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);
|
||||
}
|
||||
|
@ -368,7 +368,9 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
|
||||
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();
|
||||
|
@ -293,6 +293,9 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
|
||||
case 'd':
|
||||
flags |= ELF::XCORE_SHF_DP_SECTION;
|
||||
break;
|
||||
case 'y':
|
||||
flags |= ELF::SHF_ARM_PURECODE;
|
||||
break;
|
||||
case 'G':
|
||||
flags |= ELF::SHF_GROUP;
|
||||
break;
|
||||
|
@ -110,6 +110,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
|
||||
OS << 'c';
|
||||
if (Flags & ELF::XCORE_SHF_DP_SECTION)
|
||||
OS << 'd';
|
||||
if (Flags & ELF::SHF_ARM_PURECODE)
|
||||
OS << 'y';
|
||||
|
||||
OS << '"';
|
||||
|
||||
|
@ -423,6 +423,9 @@ void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO,
|
||||
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)
|
||||
|
@ -232,6 +232,8 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
if (Subtarget->genExecuteOnly())
|
||||
llvm_unreachable("execute-only should not generate constant pools");
|
||||
GetCPISymbol(MO.getIndex())->print(O, MAI);
|
||||
break;
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &mf) {
|
||||
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.
|
||||
|
@ -3152,7 +3152,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op,
|
||||
(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(SDValue Op, SelectionDAG &DAG) const {
|
||||
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_t SplatBits, uint64_t SplatUndef,
|
||||
|
||||
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::LowerConstantFP(SDValue Op, SelectionDAG &DAG,
|
||||
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::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
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()) {
|
||||
|
@ -398,6 +398,14 @@ class tPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
|
||||
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>
|
||||
|
@ -330,6 +330,8 @@ def DontUseVMOVSR : Predicate<"!Subtarget->preferVMOVSR() &&"
|
||||
def IsLE : Predicate<"MF->getDataLayout().isLittleEndian()">;
|
||||
def IsBE : Predicate<"MF->getDataLayout().isBigEndian()">;
|
||||
|
||||
def GenExecuteOnly : Predicate<"Subtarget->genExecuteOnly()">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ARM Flag Definitions.
|
||||
|
||||
|
@ -3381,7 +3381,9 @@ def t2B : T2I<(outs), (ins thumb_br_target:$target), IIC_Br,
|
||||
}
|
||||
|
||||
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)]>,
|
||||
|
@ -91,6 +91,8 @@ bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
|
||||
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:
|
||||
|
@ -76,6 +76,11 @@ ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
|
||||
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 &TT, const std::string &CPU,
|
||||
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(StringRef CPU, StringRef FS) {
|
||||
// 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 MachineFunction &MF) const {
|
||||
// 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 {
|
||||
|
@ -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; }
|
||||
|
@ -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(MCContext &Ctx,
|
||||
|
||||
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 *Sym) const {
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -5453,6 +5453,9 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
|
||||
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;
|
||||
}
|
||||
|
@ -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::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
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::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
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 {
|
||||
|
@ -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_imm() {
|
||||
|
||||
; 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_imm() {
|
||||
|
||||
; 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_double_imm() {
|
||||
|
||||
; 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_double_imm() {
|
||||
|
||||
; 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_notvmvn_double_imm() {
|
||||
|
||||
; 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
|
||||
}
|
||||
|
46
test/CodeGen/ARM/execute-only-big-stack-frame.ll
Normal file
46
test/CodeGen/ARM/execute-only-big-stack-frame.ll
Normal file
@ -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*)
|
23
test/CodeGen/ARM/execute-only-section.ll
Normal file
23
test/CodeGen/ARM/execute-only-section.ll
Normal file
@ -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
|
||||
}
|
82
test/CodeGen/ARM/execute-only.ll
Normal file
82
test/CodeGen/ARM/execute-only.ll
Normal file
@ -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
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
@.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)
|
||||
}
|
44
test/MC/ELF/ARM/execute-only-section.s
Normal file
44
test/MC/ELF/ARM/execute-only-section.s
Normal file
@ -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: }
|
@ -1069,6 +1069,10 @@ static const EnumEntry<unsigned> ElfAMDGPUSectionFlags[] = {
|
||||
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<ELFT>::printSections(const ELFO *Obj) {
|
||||
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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user