forked from OSchip/llvm-project
[ARM] Add hardware build attributes in assembler
In the assembler, we should emit build attributes based on the target selected with command-line options. This matches the GNU assembler's behaviour. We only do this for build attributes which describe the hardware that is expected to be available, not the ones that describe ABI compatibility. This is done by moving some of the attribute emission code to ARMTargetStreamer, so that it can be shared between the assembly and code-generation code paths. Since the assembler only creates a MCSubtargetInfo, not an ARMSubtarget, the code had to be changed to check raw features, and not use the convenience functions in ARMSubtarget. If different attributes are later specified using the .eabi_attribute directive, then they will take precedence, as happens when the same .eabi_attribute is specified twice. This must be enabled by an option, because we don't want to do this when parsing inline assembly. The attributes would match the ones emitted at the start of the file, so wouldn't actually change the emitted object file, but the extra directives would be added to every inline assembly block when emitting assembly, which we'd like to avoid. The majority of the changes in the build-attributes.ll test are just re-ordering the directives, because the hardware attributes are now emitted before the ABI ones. However, I did fix one bug which I spotted: Tag_CPU_arch_profile was not being emitted for v6M. Differential revision: https://reviews.llvm.org/D31812 llvm-svn: 300547
This commit is contained in:
parent
a3a0cccb2c
commit
7ad2e8aae1
|
@ -128,6 +128,7 @@ public:
|
|||
virtual void emitArch(unsigned Arch);
|
||||
virtual void emitArchExtension(unsigned ArchExt);
|
||||
virtual void emitObjectArch(unsigned Arch);
|
||||
void emitTargetAttributes(const MCSubtargetInfo &STI);
|
||||
virtual void finishAttributeSection();
|
||||
virtual void emitInst(uint32_t Inst, char Suffix = '\0');
|
||||
|
||||
|
|
|
@ -86,6 +86,10 @@ public:
|
|||
FeatureBits = FeatureBits_;
|
||||
}
|
||||
|
||||
bool hasFeature(unsigned Feature) const {
|
||||
return FeatureBits[Feature];
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Initialize the scheduling model and feature bits.
|
||||
///
|
||||
|
|
|
@ -589,12 +589,6 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
|
|||
ATS.finishAttributeSection();
|
||||
}
|
||||
|
||||
static bool isV8M(const ARMSubtarget *Subtarget) {
|
||||
// Note that v8M Baseline is a subset of v6T2!
|
||||
return (Subtarget->hasV8MBaselineOps() && !Subtarget->hasV6T2Ops()) ||
|
||||
Subtarget->hasV8MMainlineOps();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
|
||||
// FIXME:
|
||||
|
@ -602,39 +596,6 @@ static bool isV8M(const ARMSubtarget *Subtarget) {
|
|||
// to appear in the .ARM.attributes section in ELF.
|
||||
// Instead of subclassing the MCELFStreamer, we do the work here.
|
||||
|
||||
static ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU,
|
||||
const ARMSubtarget *Subtarget) {
|
||||
if (CPU == "xscale")
|
||||
return ARMBuildAttrs::v5TEJ;
|
||||
|
||||
if (Subtarget->hasV8Ops()) {
|
||||
if (Subtarget->isRClass())
|
||||
return ARMBuildAttrs::v8_R;
|
||||
return ARMBuildAttrs::v8_A;
|
||||
} else if (Subtarget->hasV8MMainlineOps())
|
||||
return ARMBuildAttrs::v8_M_Main;
|
||||
else if (Subtarget->hasV7Ops()) {
|
||||
if (Subtarget->isMClass() && Subtarget->hasDSP())
|
||||
return ARMBuildAttrs::v7E_M;
|
||||
return ARMBuildAttrs::v7;
|
||||
} else if (Subtarget->hasV6T2Ops())
|
||||
return ARMBuildAttrs::v6T2;
|
||||
else if (Subtarget->hasV8MBaselineOps())
|
||||
return ARMBuildAttrs::v8_M_Base;
|
||||
else if (Subtarget->hasV6MOps())
|
||||
return ARMBuildAttrs::v6S_M;
|
||||
else if (Subtarget->hasV6Ops())
|
||||
return ARMBuildAttrs::v6;
|
||||
else if (Subtarget->hasV5TEOps())
|
||||
return ARMBuildAttrs::v5TE;
|
||||
else if (Subtarget->hasV5TOps())
|
||||
return ARMBuildAttrs::v5T;
|
||||
else if (Subtarget->hasV4TOps())
|
||||
return ARMBuildAttrs::v4T;
|
||||
else
|
||||
return ARMBuildAttrs::v4;
|
||||
}
|
||||
|
||||
// Returns true if all functions have the same function attribute value.
|
||||
// It also returns true when the module has no functions.
|
||||
static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr,
|
||||
|
@ -671,89 +632,8 @@ void ARMAsmPrinter::emitAttributes() {
|
|||
static_cast<const ARMBaseTargetMachine &>(TM);
|
||||
const ARMSubtarget STI(TT, CPU, ArchFS, ATM, ATM.isLittleEndian());
|
||||
|
||||
const std::string &CPUString = STI.getCPUString();
|
||||
|
||||
if (!StringRef(CPUString).startswith("generic")) {
|
||||
// FIXME: remove krait check when GNU tools support krait cpu
|
||||
if (STI.isKrait()) {
|
||||
ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9");
|
||||
// We consider krait as a "cortex-a9" + hwdiv CPU
|
||||
// Enable hwdiv through ".arch_extension idiv"
|
||||
if (STI.hasDivide() || STI.hasDivideInARMMode())
|
||||
ATS.emitArchExtension(ARM::AEK_HWDIV | ARM::AEK_HWDIVARM);
|
||||
} else
|
||||
ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
|
||||
}
|
||||
|
||||
ATS.emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(CPUString, &STI));
|
||||
|
||||
// Tag_CPU_arch_profile must have the default value of 0 when "Architecture
|
||||
// profile is not applicable (e.g. pre v7, or cross-profile code)".
|
||||
if (STI.hasV7Ops() || isV8M(&STI)) {
|
||||
if (STI.isAClass()) {
|
||||
ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::ApplicationProfile);
|
||||
} else if (STI.isRClass()) {
|
||||
ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::RealTimeProfile);
|
||||
} else if (STI.isMClass()) {
|
||||
ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::MicroControllerProfile);
|
||||
}
|
||||
}
|
||||
|
||||
ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use,
|
||||
STI.hasARMOps() ? ARMBuildAttrs::Allowed
|
||||
: ARMBuildAttrs::Not_Allowed);
|
||||
if (isV8M(&STI)) {
|
||||
ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
|
||||
ARMBuildAttrs::AllowThumbDerived);
|
||||
} else if (STI.isThumb1Only()) {
|
||||
ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed);
|
||||
} else if (STI.hasThumb2()) {
|
||||
ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
|
||||
ARMBuildAttrs::AllowThumb32);
|
||||
}
|
||||
|
||||
if (STI.hasNEON()) {
|
||||
/* NEON is not exactly a VFP architecture, but GAS emit one of
|
||||
* neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
|
||||
if (STI.hasFPARMv8()) {
|
||||
if (STI.hasCrypto())
|
||||
ATS.emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8);
|
||||
else
|
||||
ATS.emitFPU(ARM::FK_NEON_FP_ARMV8);
|
||||
} else if (STI.hasVFP4())
|
||||
ATS.emitFPU(ARM::FK_NEON_VFPV4);
|
||||
else
|
||||
ATS.emitFPU(STI.hasFP16() ? ARM::FK_NEON_FP16 : ARM::FK_NEON);
|
||||
// Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
|
||||
if (STI.hasV8Ops())
|
||||
ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
STI.hasV8_1aOps() ? ARMBuildAttrs::AllowNeonARMv8_1a:
|
||||
ARMBuildAttrs::AllowNeonARMv8);
|
||||
} else {
|
||||
if (STI.hasFPARMv8())
|
||||
// FPv5 and FP-ARMv8 have the same instructions, so are modeled as one
|
||||
// FPU, but there are two different names for it depending on the CPU.
|
||||
ATS.emitFPU(STI.hasD16()
|
||||
? (STI.isFPOnlySP() ? ARM::FK_FPV5_SP_D16 : ARM::FK_FPV5_D16)
|
||||
: ARM::FK_FP_ARMV8);
|
||||
else if (STI.hasVFP4())
|
||||
ATS.emitFPU(STI.hasD16()
|
||||
? (STI.isFPOnlySP() ? ARM::FK_FPV4_SP_D16 : ARM::FK_VFPV4_D16)
|
||||
: ARM::FK_VFPV4);
|
||||
else if (STI.hasVFP3())
|
||||
ATS.emitFPU(STI.hasD16()
|
||||
// +d16
|
||||
? (STI.isFPOnlySP()
|
||||
? (STI.hasFP16() ? ARM::FK_VFPV3XD_FP16 : ARM::FK_VFPV3XD)
|
||||
: (STI.hasFP16() ? ARM::FK_VFPV3_D16_FP16 : ARM::FK_VFPV3_D16))
|
||||
// -d16
|
||||
: (STI.hasFP16() ? ARM::FK_VFPV3_FP16 : ARM::FK_VFPV3));
|
||||
else if (STI.hasVFP2())
|
||||
ATS.emitFPU(ARM::FK_VFPV2);
|
||||
}
|
||||
// Emit build attributes for the available hardware.
|
||||
ATS.emitTargetAttributes(STI);
|
||||
|
||||
// RW data addressing.
|
||||
if (isPositionIndependent()) {
|
||||
|
@ -846,32 +726,15 @@ void ARMAsmPrinter::emitAttributes() {
|
|||
ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
|
||||
ARMBuildAttrs::AllowIEEE754);
|
||||
|
||||
if (STI.allowsUnalignedMem())
|
||||
ATS.emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
|
||||
ARMBuildAttrs::Allowed);
|
||||
else
|
||||
ATS.emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
|
||||
ARMBuildAttrs::Not_Allowed);
|
||||
|
||||
// FIXME: add more flags to ARMBuildAttributes.h
|
||||
// 8-bytes alignment stuff.
|
||||
ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1);
|
||||
ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1);
|
||||
|
||||
// ABI_HardFP_use attribute to indicate single precision FP.
|
||||
if (STI.isFPOnlySP())
|
||||
ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
|
||||
ARMBuildAttrs::HardFPSinglePrecision);
|
||||
|
||||
// Hard float. Use both S and D registers and conform to AAPCS-VFP.
|
||||
if (STI.isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
|
||||
ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);
|
||||
|
||||
// FIXME: Should we signal R9 usage?
|
||||
|
||||
if (STI.hasFP16())
|
||||
ATS.emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
|
||||
|
||||
// FIXME: To support emitting this build attribute as GCC does, the
|
||||
// -mfp16-format option and associated plumbing must be
|
||||
// supported. For now the __fp16 type is exposed by default, so this
|
||||
|
@ -879,21 +742,6 @@ void ARMAsmPrinter::emitAttributes() {
|
|||
ATS.emitAttribute(ARMBuildAttrs::ABI_FP_16bit_format,
|
||||
ARMBuildAttrs::FP16FormatIEEE);
|
||||
|
||||
if (STI.hasMPExtension())
|
||||
ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
|
||||
|
||||
// Hardware divide in ARM mode is part of base arch, starting from ARMv8.
|
||||
// If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
|
||||
// It is not possible to produce DisallowDIV: if hwdiv is present in the base
|
||||
// arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
|
||||
// AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
|
||||
// otherwise, the default value (AllowDIVIfExists) applies.
|
||||
if (STI.hasDivideInARMMode() && !STI.hasV8Ops())
|
||||
ATS.emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);
|
||||
|
||||
if (STI.hasDSP() && isV8M(&STI))
|
||||
ATS.emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed);
|
||||
|
||||
if (MMI) {
|
||||
if (const Module *SourceModule = MMI->getModule()) {
|
||||
// ABI_PCS_wchar_t to indicate wchar_t width
|
||||
|
@ -930,16 +778,6 @@ void ARMAsmPrinter::emitAttributes() {
|
|||
else
|
||||
ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
|
||||
ARMBuildAttrs::R9IsGPR);
|
||||
|
||||
if (STI.hasTrustZone() && STI.hasVirtualization())
|
||||
ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowTZVirtualization);
|
||||
else if (STI.hasTrustZone())
|
||||
ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowTZ);
|
||||
else if (STI.hasVirtualization())
|
||||
ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowVirtualization);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -67,6 +67,9 @@ static cl::opt<ImplicitItModeTy> ImplicitItMode(
|
|||
clEnumValN(ImplicitItModeTy::ThumbOnly, "thumb",
|
||||
"Warn in ARM, emit implicit ITs in Thumb")));
|
||||
|
||||
static cl::opt<bool> AddBuildAttributes("arm-add-build-attributes",
|
||||
cl::init(false));
|
||||
|
||||
class ARMOperand;
|
||||
|
||||
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
|
||||
|
@ -540,6 +543,10 @@ public:
|
|||
// Initialize the set of available features.
|
||||
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
|
||||
|
||||
// Add build attributes based on the selected target.
|
||||
if (AddBuildAttributes)
|
||||
getTargetStreamer().emitTargetAttributes(STI);
|
||||
|
||||
// Not in an ITBlock to start with.
|
||||
ITState.CurPosition = ~0U;
|
||||
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ARMTargetMachine.h"
|
||||
#include "llvm/MC/ConstantPools.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ARMBuildAttributes.h"
|
||||
#include "llvm/Support/TargetParser.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -75,3 +79,179 @@ void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {}
|
|||
void
|
||||
ARMTargetStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) {}
|
||||
void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {}
|
||||
|
||||
static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI) {
|
||||
if (STI.getCPU() == "xscale")
|
||||
return ARMBuildAttrs::v5TEJ;
|
||||
|
||||
if (STI.hasFeature(ARM::HasV8Ops)) {
|
||||
if (STI.hasFeature(ARM::FeatureRClass))
|
||||
return ARMBuildAttrs::v8_R;
|
||||
return ARMBuildAttrs::v8_A;
|
||||
} else if (STI.hasFeature(ARM::HasV8MMainlineOps))
|
||||
return ARMBuildAttrs::v8_M_Main;
|
||||
else if (STI.hasFeature(ARM::HasV7Ops)) {
|
||||
if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP))
|
||||
return ARMBuildAttrs::v7E_M;
|
||||
return ARMBuildAttrs::v7;
|
||||
} else if (STI.hasFeature(ARM::HasV6T2Ops))
|
||||
return ARMBuildAttrs::v6T2;
|
||||
else if (STI.hasFeature(ARM::HasV8MBaselineOps))
|
||||
return ARMBuildAttrs::v8_M_Base;
|
||||
else if (STI.hasFeature(ARM::HasV6MOps))
|
||||
return ARMBuildAttrs::v6S_M;
|
||||
else if (STI.hasFeature(ARM::HasV6Ops))
|
||||
return ARMBuildAttrs::v6;
|
||||
else if (STI.hasFeature(ARM::HasV5TEOps))
|
||||
return ARMBuildAttrs::v5TE;
|
||||
else if (STI.hasFeature(ARM::HasV5TOps))
|
||||
return ARMBuildAttrs::v5T;
|
||||
else if (STI.hasFeature(ARM::HasV4TOps))
|
||||
return ARMBuildAttrs::v4T;
|
||||
else
|
||||
return ARMBuildAttrs::v4;
|
||||
}
|
||||
|
||||
static bool isV8M(const MCSubtargetInfo &STI) {
|
||||
// Note that v8M Baseline is a subset of v6T2!
|
||||
return (STI.hasFeature(ARM::HasV8MBaselineOps) &&
|
||||
!STI.hasFeature(ARM::HasV6T2Ops)) ||
|
||||
STI.hasFeature(ARM::HasV8MMainlineOps);
|
||||
}
|
||||
|
||||
/// Emit the build attributes that only depend on the hardware that we expect
|
||||
// /to be available, and not on the ABI, or any source-language choices.
|
||||
void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
|
||||
switchVendor("aeabi");
|
||||
|
||||
const StringRef CPUString = STI.getCPU();
|
||||
if (!CPUString.empty() && !CPUString.startswith("generic")) {
|
||||
// FIXME: remove krait check when GNU tools support krait cpu
|
||||
if (STI.hasFeature(ARM::ProcKrait)) {
|
||||
emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9");
|
||||
// We consider krait as a "cortex-a9" + hwdiv CPU
|
||||
// Enable hwdiv through ".arch_extension idiv"
|
||||
if (STI.hasFeature(ARM::FeatureHWDiv) ||
|
||||
STI.hasFeature(ARM::FeatureHWDivARM))
|
||||
emitArchExtension(ARM::AEK_HWDIV | ARM::AEK_HWDIVARM);
|
||||
} else {
|
||||
emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
|
||||
}
|
||||
}
|
||||
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(STI));
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureAClass)) {
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::ApplicationProfile);
|
||||
} else if (STI.hasFeature(ARM::FeatureRClass)) {
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::RealTimeProfile);
|
||||
} else if (STI.hasFeature(ARM::FeatureMClass)) {
|
||||
emitAttribute(ARMBuildAttrs::CPU_arch_profile,
|
||||
ARMBuildAttrs::MicroControllerProfile);
|
||||
}
|
||||
|
||||
emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasFeature(ARM::FeatureNoARM)
|
||||
? ARMBuildAttrs::Not_Allowed
|
||||
: ARMBuildAttrs::Allowed);
|
||||
|
||||
if (isV8M(STI)) {
|
||||
emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
|
||||
ARMBuildAttrs::AllowThumbDerived);
|
||||
} else if (STI.hasFeature(ARM::FeatureThumb2)) {
|
||||
emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
|
||||
ARMBuildAttrs::AllowThumb32);
|
||||
} else if (STI.hasFeature(ARM::HasV4TOps)) {
|
||||
emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed);
|
||||
}
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureNEON)) {
|
||||
/* NEON is not exactly a VFP architecture, but GAS emit one of
|
||||
* neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
|
||||
if (STI.hasFeature(ARM::FeatureFPARMv8)) {
|
||||
if (STI.hasFeature(ARM::FeatureCrypto))
|
||||
emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8);
|
||||
else
|
||||
emitFPU(ARM::FK_NEON_FP_ARMV8);
|
||||
} else if (STI.hasFeature(ARM::FeatureVFP4))
|
||||
emitFPU(ARM::FK_NEON_VFPV4);
|
||||
else
|
||||
emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16
|
||||
: ARM::FK_NEON);
|
||||
// Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
|
||||
if (STI.hasFeature(ARM::HasV8Ops))
|
||||
emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
|
||||
STI.hasFeature(ARM::HasV8_1aOps)
|
||||
? ARMBuildAttrs::AllowNeonARMv8_1a
|
||||
: ARMBuildAttrs::AllowNeonARMv8);
|
||||
} else {
|
||||
if (STI.hasFeature(ARM::FeatureFPARMv8))
|
||||
// FPv5 and FP-ARMv8 have the same instructions, so are modeled as one
|
||||
// FPU, but there are two different names for it depending on the CPU.
|
||||
emitFPU(STI.hasFeature(ARM::FeatureD16)
|
||||
? (STI.hasFeature(ARM::FeatureVFPOnlySP) ? ARM::FK_FPV5_SP_D16
|
||||
: ARM::FK_FPV5_D16)
|
||||
: ARM::FK_FP_ARMV8);
|
||||
else if (STI.hasFeature(ARM::FeatureVFP4))
|
||||
emitFPU(STI.hasFeature(ARM::FeatureD16)
|
||||
? (STI.hasFeature(ARM::FeatureVFPOnlySP) ? ARM::FK_FPV4_SP_D16
|
||||
: ARM::FK_VFPV4_D16)
|
||||
: ARM::FK_VFPV4);
|
||||
else if (STI.hasFeature(ARM::FeatureVFP3))
|
||||
emitFPU(
|
||||
STI.hasFeature(ARM::FeatureD16)
|
||||
// +d16
|
||||
? (STI.hasFeature(ARM::FeatureVFPOnlySP)
|
||||
? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16
|
||||
: ARM::FK_VFPV3XD)
|
||||
: (STI.hasFeature(ARM::FeatureFP16)
|
||||
? ARM::FK_VFPV3_D16_FP16
|
||||
: ARM::FK_VFPV3_D16))
|
||||
// -d16
|
||||
: (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16
|
||||
: ARM::FK_VFPV3));
|
||||
else if (STI.hasFeature(ARM::FeatureVFP2))
|
||||
emitFPU(ARM::FK_VFPV2);
|
||||
}
|
||||
|
||||
// ABI_HardFP_use attribute to indicate single precision FP.
|
||||
if (STI.hasFeature(ARM::FeatureVFPOnlySP))
|
||||
emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
|
||||
ARMBuildAttrs::HardFPSinglePrecision);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureFP16))
|
||||
emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureMP))
|
||||
emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
|
||||
|
||||
// Hardware divide in ARM mode is part of base arch, starting from ARMv8.
|
||||
// If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
|
||||
// It is not possible to produce DisallowDIV: if hwdiv is present in the base
|
||||
// arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
|
||||
// AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
|
||||
// otherwise, the default value (AllowDIVIfExists) applies.
|
||||
if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops))
|
||||
emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI))
|
||||
emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureStrictAlign))
|
||||
emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
|
||||
ARMBuildAttrs::Not_Allowed);
|
||||
else
|
||||
emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
|
||||
ARMBuildAttrs::Allowed);
|
||||
|
||||
if (STI.hasFeature(ARM::FeatureTrustZone) &&
|
||||
STI.hasFeature(ARM::FeatureVirtualization))
|
||||
emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowTZVirtualization);
|
||||
else if (STI.hasFeature(ARM::FeatureTrustZone))
|
||||
emitAttribute(ARMBuildAttrs::Virtualization_use, ARMBuildAttrs::AllowTZ);
|
||||
else if (STI.hasFeature(ARM::FeatureVirtualization))
|
||||
emitAttribute(ARMBuildAttrs::Virtualization_use,
|
||||
ARMBuildAttrs::AllowVirtualization);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,43 @@
|
|||
// RUN: llvm-mc -triple armv7a < %s -arm-add-build-attributes | FileCheck %s --check-prefix=v7A
|
||||
// RUN: llvm-mc -triple armv6m < %s -arm-add-build-attributes | FileCheck %s --check-prefix=v6M
|
||||
// RUN: llvm-mc -triple armv7m < %s -arm-add-build-attributes | FileCheck %s --check-prefix=v7M
|
||||
// RUN: llvm-mc -triple armv7a -mcpu=cortex-a15 < %s -arm-add-build-attributes | FileCheck %s --check-prefix=Cortex-A15
|
||||
|
||||
// This isn't intended to be a through check of the build attributes emitted
|
||||
// for each target (that's tested elsewhere), but just to check that the
|
||||
// hardware attributes are emitted by the assembler based on the selected
|
||||
// target when requested.
|
||||
|
||||
// v7A-NOT: .cpu
|
||||
// v7A: .eabi_attribute 6, 10 @ Tag_CPU_arch
|
||||
// v7A: .eabi_attribute 7, 65 @ Tag_CPU_arch_profile
|
||||
// v7A: .eabi_attribute 8, 1 @ Tag_ARM_ISA_use
|
||||
// v7A: .eabi_attribute 9, 2 @ Tag_THUMB_ISA_use
|
||||
// v7A: .fpu neon
|
||||
// v7A: .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access
|
||||
|
||||
// v6M-NOT: .cpu
|
||||
// v6M: .eabi_attribute 6, 12 @ Tag_CPU_arch
|
||||
// v6M: .eabi_attribute 7, 77 @ Tag_CPU_arch_profile
|
||||
// v6M: .eabi_attribute 8, 0 @ Tag_ARM_ISA_use
|
||||
// v6M: .eabi_attribute 9, 1 @ Tag_THUMB_ISA_use
|
||||
// v6M: .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access
|
||||
|
||||
// v7M-NOT: .cpu
|
||||
// v7M: .eabi_attribute 6, 10 @ Tag_CPU_arch
|
||||
// v7M: .eabi_attribute 7, 77 @ Tag_CPU_arch_profile
|
||||
// v7M: .eabi_attribute 8, 0 @ Tag_ARM_ISA_use
|
||||
// v7M: .eabi_attribute 9, 2 @ Tag_THUMB_ISA_use
|
||||
// v7M: .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access
|
||||
|
||||
// Cortex-A15: .cpu cortex-a15
|
||||
// Cortex-A15: .eabi_attribute 6, 10 @ Tag_CPU_arch
|
||||
// Cortex-A15: .eabi_attribute 7, 65 @ Tag_CPU_arch_profile
|
||||
// Cortex-A15: .eabi_attribute 8, 1 @ Tag_ARM_ISA_use
|
||||
// Cortex-A15: .eabi_attribute 9, 2 @ Tag_THUMB_ISA_use
|
||||
// Cortex-A15: .fpu neon-vfpv4
|
||||
// Cortex-A15: .eabi_attribute 36, 1 @ Tag_FP_HP_extension
|
||||
// Cortex-A15: .eabi_attribute 42, 1 @ Tag_MPextension_use
|
||||
// Cortex-A15: .eabi_attribute 44, 2 @ Tag_DIV_use
|
||||
// Cortex-A15: .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access
|
||||
// Cortex-A15: .eabi_attribute 68, 3 @ Tag_Virtualization_use
|
Loading…
Reference in New Issue