virtual void emitPad(int64_t Offset) = 0;
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
bool isVector) = 0;
+
+ virtual void switchVendor(StringRef Vendor) = 0;
+ virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0;
+ virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0;
+ virtual void emitFPU(unsigned FPU) = 0;
+ virtual void finishAttributeSection() = 0;
};
/// MCStreamer - Streaming machine code generation interface. This interface
[ProcR5, HasV7Ops, FeatureDB,
FeatureVFP3, FeatureDSPThumb2,
FeatureHasRAS, FeatureVFPOnlySP,
- FeatureRClass]>;
+ FeatureD16, FeatureRClass]>;
// V7M Processors.
def : ProcNoItin<"cortex-m3", [HasV7Ops,
FeatureThumb2, FeatureNoARM, FeatureDB,
FeatureHWDiv, FeatureDSPThumb2,
FeatureT2XtPk, FeatureVFP4,
- FeatureVFPOnlySP, FeatureMClass]>;
+ FeatureVFPOnlySP, FeatureD16,
+ FeatureMClass]>;
// Swift uArch Processors.
def : ProcessorModel<"swift", SwiftModel,
#include "ARM.h"
#include "ARMBuildAttrs.h"
#include "ARMConstantPoolValue.h"
+#include "ARMFPUName.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMTargetMachine.h"
#include "ARMTargetObjectFile.h"
#include <cctype>
using namespace llvm;
-namespace {
-
- // Per section and per symbol attributes are not supported.
- // To implement them we would need the ability to delay this emission
- // until the assembly file is fully parsed/generated as only then do we
- // know the symbol and section numbers.
- class AttributeEmitter {
- public:
- virtual void MaybeSwitchVendor(StringRef Vendor) = 0;
- virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0;
- virtual void EmitTextAttribute(unsigned Attribute, StringRef String) = 0;
- virtual void Finish() = 0;
- virtual ~AttributeEmitter() {}
- };
-
- class AsmAttributeEmitter : public AttributeEmitter {
- MCStreamer &Streamer;
-
- public:
- AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {}
- void MaybeSwitchVendor(StringRef Vendor) { }
-
- void EmitAttribute(unsigned Attribute, unsigned Value) {
- Streamer.EmitRawText("\t.eabi_attribute " +
- Twine(Attribute) + ", " + Twine(Value));
- }
-
- void EmitTextAttribute(unsigned Attribute, StringRef String) {
- switch (Attribute) {
- default: llvm_unreachable("Unsupported Text attribute in ASM Mode");
- case ARMBuildAttrs::CPU_name:
- Streamer.EmitRawText(StringRef("\t.cpu ") + String.lower());
- break;
- /* GAS requires .fpu to be emitted regardless of EABI attribute */
- case ARMBuildAttrs::Advanced_SIMD_arch:
- case ARMBuildAttrs::VFP_arch:
- Streamer.EmitRawText(StringRef("\t.fpu ") + String.lower());
- break;
- }
- }
- void Finish() { }
- };
-
- class ObjectAttributeEmitter : public AttributeEmitter {
- // This structure holds all attributes, accounting for
- // their string/numeric value, so we can later emmit them
- // in declaration order, keeping all in the same vector
- struct AttributeItemType {
- enum {
- HiddenAttribute = 0,
- NumericAttribute,
- TextAttribute
- } Type;
- unsigned Tag;
- unsigned IntValue;
- StringRef StringValue;
- };
-
- MCObjectStreamer &Streamer;
- StringRef CurrentVendor;
- SmallVector<AttributeItemType, 64> Contents;
-
- // Account for the ULEB/String size of each item,
- // not just the number of items
- size_t ContentsSize;
- // FIXME: this should be in a more generic place, but
- // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf
- size_t getULEBSize(int Value) {
- size_t Size = 0;
- do {
- Value >>= 7;
- Size += sizeof(int8_t); // Is this really necessary?
- } while (Value);
- return Size;
- }
-
- public:
- ObjectAttributeEmitter(MCObjectStreamer &Streamer_) :
- Streamer(Streamer_), CurrentVendor(""), ContentsSize(0) { }
-
- void MaybeSwitchVendor(StringRef Vendor) {
- assert(!Vendor.empty() && "Vendor cannot be empty.");
-
- if (CurrentVendor.empty())
- CurrentVendor = Vendor;
- else if (CurrentVendor == Vendor)
- return;
- else
- Finish();
-
- CurrentVendor = Vendor;
-
- assert(Contents.size() == 0);
- }
-
- void EmitAttribute(unsigned Attribute, unsigned Value) {
- AttributeItemType attr = {
- AttributeItemType::NumericAttribute,
- Attribute,
- Value,
- StringRef("")
- };
- ContentsSize += getULEBSize(Attribute);
- ContentsSize += getULEBSize(Value);
- Contents.push_back(attr);
- }
-
- void EmitTextAttribute(unsigned Attribute, StringRef String) {
- AttributeItemType attr = {
- AttributeItemType::TextAttribute,
- Attribute,
- 0,
- String
- };
- ContentsSize += getULEBSize(Attribute);
- // String + \0
- ContentsSize += String.size()+1;
-
- Contents.push_back(attr);
- }
-
- void Finish() {
- // Vendor size + Vendor name + '\0'
- const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
-
- // Tag + Tag Size
- const size_t TagHeaderSize = 1 + 4;
-
- Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
- Streamer.EmitBytes(CurrentVendor);
- Streamer.EmitIntValue(0, 1); // '\0'
-
- Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
- Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
-
- // Size should have been accounted for already, now
- // emit each field as its type (ULEB or String)
- for (unsigned int i=0; i<Contents.size(); ++i) {
- AttributeItemType item = Contents[i];
- Streamer.EmitULEB128IntValue(item.Tag);
- switch (item.Type) {
- default: llvm_unreachable("Invalid attribute type");
- case AttributeItemType::NumericAttribute:
- Streamer.EmitULEB128IntValue(item.IntValue);
- break;
- case AttributeItemType::TextAttribute:
- Streamer.EmitBytes(item.StringValue.upper());
- Streamer.EmitIntValue(0, 1); // '\0'
- break;
- }
- }
-
- Contents.clear();
- }
- };
-
-} // end of anonymous namespace
-
/// EmitDwarfRegOp - Emit dwarf register operation.
void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
bool Indirect) const {
}
void ARMAsmPrinter::emitAttributes() {
+ MCTargetStreamer &TS = OutStreamer.getTargetStreamer();
+ ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
- emitARMAttributeSection();
-
- /* GAS expect .fpu to be emitted, regardless of VFP build attribute */
- bool emitFPU = false;
- AttributeEmitter *AttrEmitter;
- if (OutStreamer.hasRawTextSupport()) {
- AttrEmitter = new AsmAttributeEmitter(OutStreamer);
- emitFPU = true;
- } else {
- MCObjectStreamer &O = static_cast<MCObjectStreamer&>(OutStreamer);
- AttrEmitter = new ObjectAttributeEmitter(O);
- }
-
- AttrEmitter->MaybeSwitchVendor("aeabi");
+ ATS.switchVendor("aeabi");
std::string CPUString = Subtarget->getCPUString();
if (CPUString != "generic")
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
+ ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
- AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch,
- getArchForCPU(CPUString, Subtarget));
+ ATS.emitAttribute(ARMBuildAttrs::CPU_arch,
+ getArchForCPU(CPUString, Subtarget));
if (Subtarget->isAClass()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile,
- ARMBuildAttrs::ApplicationProfile);
+ ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::ApplicationProfile);
} else if (Subtarget->isRClass()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile,
- ARMBuildAttrs::RealTimeProfile);
+ ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::RealTimeProfile);
} else if (Subtarget->isMClass()){
- AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile,
- ARMBuildAttrs::MicroControllerProfile);
+ ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::MicroControllerProfile);
}
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ?
- ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed);
+ ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ?
+ ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed);
if (Subtarget->isThumb1Only()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use,
- ARMBuildAttrs::Allowed);
+ ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
+ ARMBuildAttrs::Allowed);
} else if (Subtarget->hasThumb2()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use,
- ARMBuildAttrs::AllowThumb32);
+ ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
+ ARMBuildAttrs::AllowThumb32);
}
- if (Subtarget->hasNEON() && emitFPU) {
+ if (Subtarget->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 (Subtarget->hasFPARMv8()) {
if (Subtarget->hasCrypto())
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
- "crypto-neon-fp-armv8");
+ ATS.emitFPU(ARM::CRYPTO_NEON_FP_ARMV8);
else
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
- "neon-fp-armv8");
+ ATS.emitFPU(ARM::NEON_FP_ARMV8);
}
else if (Subtarget->hasVFP4())
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
- "neon-vfpv4");
+ ATS.emitFPU(ARM::NEON_VFPV4);
else
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch, "neon");
- /* If emitted for NEON, omit from VFP below, since you can have both
- * NEON and VFP in build attributes but only one .fpu */
- emitFPU = false;
- }
-
- /* FPARMv8 + .fpu */
- if (Subtarget->hasFPARMv8()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch,
- ARMBuildAttrs::AllowFPARMv8A);
- if (emitFPU)
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "fp-armv8");
- /* VFPv4 + .fpu */
- } else if (Subtarget->hasVFP4()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch,
- Subtarget->isFPOnlySP() ? ARMBuildAttrs::AllowFPv4B :
- ARMBuildAttrs::AllowFPv4A);
- if (emitFPU)
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv4");
-
- /* VFPv3 + .fpu */
- } else if (Subtarget->hasVFP3()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch,
- Subtarget->isFPOnlySP() ? ARMBuildAttrs::AllowFPv3B :
- ARMBuildAttrs::AllowFPv3A);
- if (emitFPU)
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv3");
-
- /* VFPv2 + .fpu */
- } else if (Subtarget->hasVFP2()) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch,
- ARMBuildAttrs::AllowFPv2);
- if (emitFPU)
- AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv2");
- }
-
- /* TODO: ARMBuildAttrs::Allowed is not completely accurate,
- * since NEON can have 1 (allowed) or 2 (MAC operations) */
- if (Subtarget->hasNEON()) {
+ ATS.emitFPU(ARM::NEON);
+ // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
if (Subtarget->hasV8Ops())
- AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
- ARMBuildAttrs::AllowedNeonV8);
- else
- AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
- ARMBuildAttrs::Allowed);
+ ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeonARMv8);
+ } else {
+ if (Subtarget->hasFPARMv8())
+ ATS.emitFPU(ARM::FP_ARMV8);
+ else if (Subtarget->hasVFP4())
+ ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV4_D16 : ARM::VFPV4);
+ else if (Subtarget->hasVFP3())
+ ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV3_D16 : ARM::VFPV3);
+ else if (Subtarget->hasVFP2())
+ ATS.emitFPU(ARM::VFPV2);
}
// Signal various FP modes.
if (!TM.Options.UnsafeFPMath) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal,
- ARMBuildAttrs::Allowed);
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
- ARMBuildAttrs::Allowed);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::Allowed);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
+ ARMBuildAttrs::Allowed);
}
if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model,
- ARMBuildAttrs::Allowed);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
+ ARMBuildAttrs::Allowed);
else
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model,
- ARMBuildAttrs::AllowIEE754);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
+ ARMBuildAttrs::AllowIEE754);
// FIXME: add more flags to ARMBuildAttrs.h
// 8-bytes alignment stuff.
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1);
// Hard float. Use both S and D registers and conform to AAPCS-VFP.
if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard) {
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
- AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3);
+ ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, 1);
}
// FIXME: Should we signal R9 usage?
if (Subtarget->hasDivide()) {
// Check if hardware divide is only available in thumb2 or ARM as well.
- AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use,
+ ATS.emitAttribute(ARMBuildAttrs::DIV_use,
Subtarget->hasDivideInARMMode() ? ARMBuildAttrs::AllowDIVExt :
ARMBuildAttrs::AllowDIVIfExists);
}
- AttrEmitter->Finish();
- delete AttrEmitter;
+ ATS.finishAttributeSection();
}
void ARMAsmPrinter::emitARMAttributeSection() {
#ifndef __TARGET_ARMBUILDATTRS_H__
#define __TARGET_ARMBUILDATTRS_H__
+namespace llvm {
namespace ARMBuildAttrs {
+
enum SpecialAttr {
// This is for the .cpu asm attr. It translates into one or more
// AttrType (below) entries in the .ARM.attributes section in the ELF.
- SEL_CPU
+ SEL_CPU
};
enum AttrType {
v8 = 14 // v8, AArch32
};
- enum CPUArchProfile { // (=7), uleb128
+ enum CPUArchProfile { // (=7), uleb128
Not_Applicable = 0, // pre v7, or cross-profile code
ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8)
RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4)
};
// The following have a lot of common use cases
- enum {
+ enum {
//ARMISAUse (=8), uleb128 and THUMBISAUse (=9), uleb128
Not_Allowed = 0,
Allowed = 1,
- AllowedNeonV8 = 3,
// FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10)
AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA)
AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA)
- AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31
- AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA)
+ AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31
+ AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA)
AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31
AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted
AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only D0-D15, S0-S31
// Tag_WMMX_arch, (=11), uleb128
AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions)
-
+
// Tag_WMMX_arch, (=11), uleb128
AllowWMMXv1 = 2, // The user permitted this entity to use WMMX v2
- // Tag_ABI_FP_denormal, (=20), uleb128
+ // Tag_Advanced_SIMD_arch, (=12), uleb128
+ AllowNeon = 1, // SIMDv1 was permitted
+ AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations)
+ AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
+
+ // Tag_ABI_FP_denormal, (=20), uleb128
PreserveFPSign = 2, // sign when flushed-to-zero is preserved
// Tag_ABI_FP_number_model, (=23), uleb128
AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI])
AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
+ // Tag_ABI_HardFP_use, (=27), uleb128
+ HardFPSinglePrecision = 1, // Single-precision only
+ HardFPImplied = 3, // FP use should be implied by Tag_FP_arch
+
// Tag_DIV_use, (=44), uleb128
AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no info exists.
DisallowDIV = 1, // Hardware divide explicitly disallowed
AllowDIVExt = 2 // Allow hardware divide as optional architecture extension above
// the base arch specified by Tag_CPU_arch and Tag_CPU_arch_profile.
};
-}
+
+} // namespace ARMBuildAttrs
+} // namespace llvm
#endif // __TARGET_ARMBUILDATTRS_H__
--- /dev/null
+//===-- ARMFPUName.def - List of the ARM FPU names --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the list of the supported ARM FPU names.
+//
+//===----------------------------------------------------------------------===//
+
+// NOTE: NO INCLUDE GUARD DESIRED!
+
+#ifndef ARM_FPU_NAME
+#error "You must define ARM_FPU_NAME(NAME, ID) before including ARMFPUName.h"
+#endif
+
+ARM_FPU_NAME("vfp", VFP)
+ARM_FPU_NAME("vfpv2", VFPV2)
+ARM_FPU_NAME("vfpv3", VFPV3)
+ARM_FPU_NAME("vfpv3-d16", VFPV3_D16)
+ARM_FPU_NAME("vfpv4", VFPV4)
+ARM_FPU_NAME("vfpv4-d16", VFPV4_D16)
+ARM_FPU_NAME("fp-armv8", FP_ARMV8)
+ARM_FPU_NAME("neon", NEON)
+ARM_FPU_NAME("neon-vfpv4", NEON_VFPV4)
+ARM_FPU_NAME("neon-fp-armv8", NEON_FP_ARMV8)
+ARM_FPU_NAME("crypto-neon-fp-armv8", CRYPTO_NEON_FP_ARMV8)
+
+#undef ARM_FPU_NAME
--- /dev/null
+//===-- ARMFPUName.h - List of the ARM FPU names ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARMFPUNAME_H
+#define ARMFPUNAME_H
+
+namespace llvm {
+namespace ARM {
+
+enum FPUKind {
+ INVALID_FPU = 0
+
+#define ARM_FPU_NAME(NAME, ID) , ID
+#include "ARMFPUName.def"
+};
+
+} // namespace ARM
+} // namespace llvm
+
+#endif // ARMFPUNAME_H
//
//===----------------------------------------------------------------------===//
+#include "ARMBuildAttrs.h"
+#include "ARMFPUName.h"
#include "ARMFeatures.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "MCTargetDesc/ARMAddressingModes.h"
bool parseDirectiveUnreq(SMLoc L);
bool parseDirectiveArch(SMLoc L);
bool parseDirectiveEabiAttr(SMLoc L);
+ bool parseDirectiveCPU(SMLoc L);
+ bool parseDirectiveFPU(SMLoc L);
bool parseDirectiveFnStart(SMLoc L);
bool parseDirectiveFnEnd(SMLoc L);
bool parseDirectiveCantUnwind(SMLoc L);
return parseDirectiveArch(DirectiveID.getLoc());
else if (IDVal == ".eabi_attribute")
return parseDirectiveEabiAttr(DirectiveID.getLoc());
+ else if (IDVal == ".cpu")
+ return parseDirectiveCPU(DirectiveID.getLoc());
+ else if (IDVal == ".fpu")
+ return parseDirectiveFPU(DirectiveID.getLoc());
else if (IDVal == ".fnstart")
return parseDirectiveFnStart(DirectiveID.getLoc());
else if (IDVal == ".fnend")
/// parseDirectiveEabiAttr
/// ::= .eabi_attribute int, int
bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
- return true;
+ if (Parser.getTok().isNot(AsmToken::Integer))
+ return Error(L, "integer expected");
+ int64_t Tag = Parser.getTok().getIntVal();
+ Parser.Lex(); // eat tag integer
+
+ if (Parser.getTok().isNot(AsmToken::Comma))
+ return Error(L, "comma expected");
+ Parser.Lex(); // skip comma
+
+ L = Parser.getTok().getLoc();
+ if (Parser.getTok().isNot(AsmToken::Integer))
+ return Error(L, "integer expected");
+ int64_t Value = Parser.getTok().getIntVal();
+ Parser.Lex(); // eat value integer
+
+ getTargetStreamer().emitAttribute(Tag, Value);
+ return false;
+}
+
+/// parseDirectiveCPU
+/// ::= .cpu str
+bool ARMAsmParser::parseDirectiveCPU(SMLoc L) {
+ StringRef CPU = getParser().parseStringToEndOfStatement().trim();
+ getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU);
+ return false;
+}
+
+/// parseDirectiveFPU
+/// ::= .fpu str
+bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
+ StringRef FPU = getParser().parseStringToEndOfStatement().trim();
+
+ unsigned ID = StringSwitch<unsigned>(FPU)
+#define ARM_FPU_NAME(NAME, ID) .Case(NAME, ARM::ID)
+#include "ARMFPUName.def"
+ .Default(ARM::INVALID_FPU);
+
+ if (ID == ARM::INVALID_FPU)
+ return Error(L, "Unknown FPU name");
+
+ getTargetStreamer().emitFPU(ID);
+ return false;
}
/// parseDirectiveFnStart
//
//===----------------------------------------------------------------------===//
+#include "ARMBuildAttrs.h"
+#include "ARMFPUName.h"
#include "ARMRegisterInfo.h"
#include "ARMUnwindOp.h"
#include "ARMUnwindOpAsm.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
using namespace llvm;
return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
}
+static const char *GetFPUName(unsigned ID) {
+ switch (ID) {
+ default:
+ llvm_unreachable("Unknown FPU kind");
+ break;
+#define ARM_FPU_NAME(NAME, ID) case ARM::ID: return NAME;
+#include "ARMFPUName.def"
+ }
+ return NULL;
+}
+
namespace {
class ARMELFStreamer;
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
bool isVector);
+ virtual void switchVendor(StringRef Vendor);
+ virtual void emitAttribute(unsigned Attribute, unsigned Value);
+ virtual void emitTextAttribute(unsigned Attribute, StringRef String);
+ virtual void emitFPU(unsigned FPU);
+ virtual void finishAttributeSection();
+
public:
ARMTargetAsmStreamer(formatted_raw_ostream &OS, MCInstPrinter &InstPrinter);
};
OS << "}\n";
}
+void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {
+}
+void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
+ OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value) << "\n";
+}
+void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
+ StringRef String) {
+ switch (Attribute) {
+ default: llvm_unreachable("Unsupported Text attribute in ASM Mode");
+ case ARMBuildAttrs::CPU_name:
+ OS << "\t.cpu\t" << String.lower() << "\n";
+ break;
+ }
+}
+void ARMTargetAsmStreamer::emitFPU(unsigned FPU) {
+ OS << "\t.fpu\t" << GetFPUName(FPU) << "\n";
+}
+void ARMTargetAsmStreamer::finishAttributeSection() {
+}
class ARMTargetELFStreamer : public ARMTargetStreamer {
+private:
+ // This structure holds all attributes, accounting for
+ // their string/numeric value, so we can later emmit them
+ // in declaration order, keeping all in the same vector
+ struct AttributeItem {
+ enum {
+ HiddenAttribute = 0,
+ NumericAttribute,
+ TextAttribute
+ } Type;
+ unsigned Tag;
+ unsigned IntValue;
+ StringRef StringValue;
+
+ static bool LessTag(const AttributeItem &LHS, const AttributeItem &RHS) {
+ return (LHS.Tag < RHS.Tag);
+ }
+ };
+
+ StringRef CurrentVendor;
+ unsigned FPU;
+ SmallVector<AttributeItem, 64> Contents;
+
+ const MCSection *AttributeSection;
+
+ // FIXME: this should be in a more generic place, but
+ // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf
+ static size_t getULEBSize(int Value) {
+ size_t Size = 0;
+ do {
+ Value >>= 7;
+ Size += sizeof(int8_t); // Is this really necessary?
+ } while (Value);
+ return Size;
+ }
+
+ AttributeItem *getAttributeItem(unsigned Attribute) {
+ for (size_t i = 0; i < Contents.size(); ++i)
+ if (Contents[i].Tag == Attribute)
+ return &Contents[i];
+ return 0;
+ }
+
+ void setAttributeItem(unsigned Attribute, unsigned Value,
+ bool OverwriteExisting) {
+ // Look for existing attribute item
+ if (AttributeItem *Item = getAttributeItem(Attribute)) {
+ if (!OverwriteExisting)
+ return;
+ Item->IntValue = Value;
+ return;
+ }
+
+ // Create new attribute item
+ AttributeItem Item = {
+ AttributeItem::NumericAttribute,
+ Attribute,
+ Value,
+ StringRef("")
+ };
+ Contents.push_back(Item);
+ }
+
+ void setAttributeItem(unsigned Attribute, StringRef Value,
+ bool OverwriteExisting) {
+ // Look for existing attribute item
+ if (AttributeItem *Item = getAttributeItem(Attribute)) {
+ if (!OverwriteExisting)
+ return;
+ Item->StringValue = Value;
+ return;
+ }
+
+ // Create new attribute item
+ AttributeItem Item = {
+ AttributeItem::TextAttribute,
+ Attribute,
+ 0,
+ Value
+ };
+ Contents.push_back(Item);
+ }
+
+ void emitFPUDefaultAttributes();
+
ARMELFStreamer &getStreamer();
+
virtual void emitFnStart();
virtual void emitFnEnd();
virtual void emitCantUnwind();
virtual void emitPad(int64_t Offset);
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
bool isVector);
+
+ virtual void switchVendor(StringRef Vendor);
+ virtual void emitAttribute(unsigned Attribute, unsigned Value);
+ virtual void emitTextAttribute(unsigned Attribute, StringRef String);
+ virtual void emitFPU(unsigned FPU);
+ virtual void finishAttributeSection();
+
+ size_t calculateContentSize() const;
+
+public:
+ ARMTargetELFStreamer()
+ : ARMTargetStreamer(), CurrentVendor("aeabi"), FPU(ARM::INVALID_FPU),
+ AttributeSection(0) {
+ }
};
/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
~ARMELFStreamer() {}
+ virtual void FinishImpl();
+
// ARM exception handling directives
void emitFnStart();
void emitFnEnd();
bool isVector) {
getStreamer().emitRegSave(RegList, isVector);
}
+void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
+ assert(!Vendor.empty() && "Vendor cannot be empty.");
+
+ if (CurrentVendor == Vendor)
+ return;
+
+ if (!CurrentVendor.empty())
+ finishAttributeSection();
+
+ assert(Contents.empty() &&
+ ".ARM.attributes should be flushed before changing vendor");
+ CurrentVendor = Vendor;
+
+}
+void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
+ setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
+}
+void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
+ StringRef Value) {
+ setAttributeItem(Attribute, Value, /* OverwriteExisting= */ true);
+}
+void ARMTargetELFStreamer::emitFPU(unsigned Value) {
+ FPU = Value;
+}
+void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
+ switch (FPU) {
+ case ARM::VFP:
+ case ARM::VFPV2:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv2,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::VFPV3:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv3A,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::VFPV3_D16:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv3B,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::VFPV4:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv4A,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::VFPV4_D16:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv4B,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::FP_ARMV8:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPARMv8A,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::NEON:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv3A,
+ /* OverwriteExisting= */ false);
+ setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeon,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::NEON_VFPV4:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPv4A,
+ /* OverwriteExisting= */ false);
+ setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeon2,
+ /* OverwriteExisting= */ false);
+ break;
+
+ case ARM::NEON_FP_ARMV8:
+ case ARM::CRYPTO_NEON_FP_ARMV8:
+ setAttributeItem(ARMBuildAttrs::VFP_arch,
+ ARMBuildAttrs::AllowFPARMv8A,
+ /* OverwriteExisting= */ false);
+ setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeonARMv8,
+ /* OverwriteExisting= */ false);
+ break;
+
+ default:
+ report_fatal_error("Unknown FPU: " + Twine(FPU));
+ break;
+ }
+}
+size_t ARMTargetELFStreamer::calculateContentSize() const {
+ size_t Result = 0;
+ for (size_t i = 0; i < Contents.size(); ++i) {
+ AttributeItem item = Contents[i];
+ switch (item.Type) {
+ case AttributeItem::HiddenAttribute:
+ break;
+ case AttributeItem::NumericAttribute:
+ Result += getULEBSize(item.Tag);
+ Result += getULEBSize(item.IntValue);
+ break;
+ case AttributeItem::TextAttribute:
+ Result += getULEBSize(item.Tag);
+ Result += item.StringValue.size() + 1; // string + '\0'
+ break;
+ }
+ }
+ return Result;
+}
+void ARMTargetELFStreamer::finishAttributeSection() {
+ // <format-version>
+ // [ <section-length> "vendor-name"
+ // [ <file-tag> <size> <attribute>*
+ // | <section-tag> <size> <section-number>* 0 <attribute>*
+ // | <symbol-tag> <size> <symbol-number>* 0 <attribute>*
+ // ]+
+ // ]*
+
+ if (FPU != ARM::INVALID_FPU)
+ emitFPUDefaultAttributes();
+
+ if (Contents.empty())
+ return;
+
+ std::sort(Contents.begin(), Contents.end(), AttributeItem::LessTag);
+
+ ARMELFStreamer &Streamer = getStreamer();
+
+ // Switch to .ARM.attributes section
+ if (AttributeSection) {
+ Streamer.SwitchSection(AttributeSection);
+ } else {
+ AttributeSection =
+ Streamer.getContext().getELFSection(".ARM.attributes",
+ ELF::SHT_ARM_ATTRIBUTES,
+ 0,
+ SectionKind::getMetadata());
+ Streamer.SwitchSection(AttributeSection);
+
+ // Format version
+ Streamer.EmitIntValue(0x41, 1);
+ }
+
+ // Vendor size + Vendor name + '\0'
+ const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1;
+
+ // Tag + Tag Size
+ const size_t TagHeaderSize = 1 + 4;
+
+ const size_t ContentsSize = calculateContentSize();
+
+ Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4);
+ Streamer.EmitBytes(CurrentVendor);
+ Streamer.EmitIntValue(0, 1); // '\0'
+
+ Streamer.EmitIntValue(ARMBuildAttrs::File, 1);
+ Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4);
+
+ // Size should have been accounted for already, now
+ // emit each field as its type (ULEB or String)
+ for (size_t i = 0; i < Contents.size(); ++i) {
+ AttributeItem item = Contents[i];
+ Streamer.EmitULEB128IntValue(item.Tag);
+ switch (item.Type) {
+ default: llvm_unreachable("Invalid attribute type");
+ case AttributeItem::NumericAttribute:
+ Streamer.EmitULEB128IntValue(item.IntValue);
+ break;
+ case AttributeItem::TextAttribute:
+ Streamer.EmitBytes(item.StringValue.upper());
+ Streamer.EmitIntValue(0, 1); // '\0'
+ break;
+ }
+ }
+
+ Contents.clear();
+ FPU = ARM::INVALID_FPU;
+}
+
+void ARMELFStreamer::FinishImpl() {
+ MCTargetStreamer &TS = getTargetStreamer();
+ ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
+ ATS.finishAttributeSection();
+
+ MCELFStreamer::FinishImpl();
+}
inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
unsigned Type,
+; This tests that MC/asm header conversion is smooth and that the
+; build attributes are correct
+
; RUN: llc < %s -mtriple=armv6-linux-gnueabi | FileCheck %s --check-prefix=V6
; RUN: llc < %s -mtriple=thumbv6m-linux-gnueabi | FileCheck %s --check-prefix=V6M
; RUN: llc < %s -mtriple=armv6-linux-gnueabi -mcpu=arm1156t2f-s | FileCheck %s --check-prefix=ARM1156T2F-S
; RUN: llc < %s -mtriple=armv8-linux-gnueabi -mattr=-crypto | FileCheck %s --check-prefix=V8-FPARMv8-NEON
; RUN: llc < %s -mtriple=armv8-linux-gnueabi | FileCheck %s --check-prefix=V8-FPARMv8-NEON-CRYPTO
; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a9 | FileCheck %s --check-prefix=CORTEX-A9
+; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CORTEX-A15
; RUN: llc < %s -mtriple=thumbv6m-linux-gnueabi -mcpu=cortex-m0 | FileCheck %s --check-prefix=CORTEX-M0
; RUN: llc < %s -mtriple=thumbv7m-linux-gnueabi -mcpu=cortex-m4 | FileCheck %s --check-prefix=CORTEX-M4
; RUN: llc < %s -mtriple=armv7r-linux-gnueabi -mcpu=cortex-r5 | FileCheck %s --check-prefix=CORTEX-R5
; RUN: llc < %s -mtriple=armv8-linux-gnueabi -mcpu=cortex-a53 | FileCheck %s --check-prefix=CORTEX-A53
; RUN: llc < %s -mtriple=armv8-linux-gnueabi -mcpu=cortex-a57 | FileCheck %s --check-prefix=CORTEX-A57
-; This tests that MC/asm header conversion is smooth and that build attributes are correct
-;
; V6: .eabi_attribute 6, 6
; V6: .eabi_attribute 8, 1
; ARM1156T2F-S: .eabi_attribute 6, 8
; ARM1156T2F-S: .eabi_attribute 8, 1
; ARM1156T2F-S: .eabi_attribute 9, 2
-; ARM1156T2F-S: .eabi_attribute 10, 2
; ARM1156T2F-S: .fpu vfpv2
; ARM1156T2F-S: .eabi_attribute 20, 1
; ARM1156T2F-S: .eabi_attribute 21, 1
; V8-FPARMv8: .syntax unified
; V8-FPARMv8: .eabi_attribute 6, 14
-; V8-FPARMv8: .eabi_attribute 10, 7
; V8-FPARMv8: .fpu fp-armv8
; V8-NEON: .syntax unified
; V8-FPARMv8-NEON: .syntax unified
; V8-FPARMv8-NEON: .eabi_attribute 6, 14
; V8-FPARMv8-NEON: .fpu neon-fp-armv8
-; V8-FPARMv8-NEON: .eabi_attribute 10, 7
; V8-FPARMv8-NEON: .eabi_attribute 12, 3
; V8-FPARMv8-NEON-CRYPTO: .syntax unified
; V8-FPARMv8-NEON-CRYPTO: .eabi_attribute 6, 14
; V8-FPARMv8-NEON-CRYPTO: .fpu crypto-neon-fp-armv8
-; V8-FPARMv8-NEON-CRYPTO: .eabi_attribute 10, 7
; V8-FPARMv8-NEON-CRYPTO: .eabi_attribute 12, 3
; CORTEX-A9: .cpu cortex-a9
; CORTEX-A9: .eabi_attribute 8, 1
; CORTEX-A9: .eabi_attribute 9, 2
; CORTEX-A9: .fpu neon
-; CORTEX-A9: .eabi_attribute 10, 3
-; CORTEX-A9: .eabi_attribute 12, 1
; CORTEX-A9: .eabi_attribute 20, 1
; CORTEX-A9: .eabi_attribute 21, 1
; CORTEX-A9: .eabi_attribute 23, 3
; CORTEX-A9: .eabi_attribute 24, 1
; CORTEX-A9: .eabi_attribute 25, 1
+; CORTEX-A15: .cpu cortex-a15
+; CORTEX-A15: .eabi_attribute 6, 10
+; CORTEX-A15: .eabi_attribute 7, 65
+; CORTEX-A15: .eabi_attribute 8, 1
+; CORTEX-A15: .eabi_attribute 9, 2
+; CORTEX-A15: .fpu neon-vfpv4
+; CORTEX-A15: .eabi_attribute 20, 1
+; CORTEX-A15: .eabi_attribute 21, 1
+; CORTEX-A15: .eabi_attribute 23, 3
+; CORTEX-A15: .eabi_attribute 24, 1
+; CORTEX-A15: .eabi_attribute 25, 1
+; CORTEX-A15: .eabi_attribute 44, 2
+
; CORTEX-M0: .cpu cortex-m0
; CORTEX-M0: .eabi_attribute 6, 12
; CORTEX-M0: .eabi_attribute 7, 77
; CORTEX-M4: .eabi_attribute 7, 77
; CORTEX-M4: .eabi_attribute 8, 0
; CORTEX-M4: .eabi_attribute 9, 2
-; CORTEX-M4: .eabi_attribute 10, 6
-; CORTEX-M4: .fpu vfpv4
+; CORTEX-M4: .fpu vfpv4-d16
; CORTEX-M4: .eabi_attribute 20, 1
; CORTEX-M4: .eabi_attribute 21, 1
; CORTEX-M4: .eabi_attribute 23, 3
; CORTEX-R5: .eabi_attribute 7, 82
; CORTEX-R5: .eabi_attribute 8, 1
; CORTEX-R5: .eabi_attribute 9, 2
-; CORTEX-R5: .eabi_attribute 10, 4
-; CORTEX-R5: .fpu vfpv3
+; CORTEX-R5: .fpu vfpv3-d16
; CORTEX-R5: .eabi_attribute 20, 1
; CORTEX-R5: .eabi_attribute 21, 1
; CORTEX-R5: .eabi_attribute 23, 3
; CORTEX-A53: .eabi_attribute 8, 1
; CORTEX-A53: .eabi_attribute 9, 2
; CORTEX-A53: .fpu crypto-neon-fp-armv8
-; CORTEX-A53: .eabi_attribute 10, 7
; CORTEX-A53: .eabi_attribute 12, 3
; CORTEX-A53: .eabi_attribute 24, 1
; CORTEX-A53: .eabi_attribute 25, 1
; CORTEX-A57: .eabi_attribute 8, 1
; CORTEX-A57: .eabi_attribute 9, 2
; CORTEX-A57: .fpu crypto-neon-fp-armv8
-; CORTEX-A57: .eabi_attribute 10, 7
; CORTEX-A57: .eabi_attribute 12, 3
; CORTEX-A57: .eabi_attribute 24, 1
; CORTEX-A57: .eabi_attribute 25, 1
-; RUN: llc %s -mtriple=arm-linux-gnueabi -filetype=obj -o - | \
-; RUN: llvm-readobj -s -sd | FileCheck -check-prefix=BASIC %s
-; RUN: llc %s -mtriple=armv7-linux-gnueabi -march=arm -mcpu=cortex-a8 \
-; RUN: -mattr=-neon,-vfp3,+vfp2 \
-; RUN: -arm-reserve-r9 -filetype=obj -o - | \
-; RUN: llvm-readobj -s -sd | FileCheck -check-prefix=CORTEXA8 %s
+; This tests that the expected ARM attributes are emitted.
+; RUN: llc < %s -mtriple=arm-linux-gnueabi -filetype=obj -o - \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=BASIC
+; RUN: llc < %s -mtriple=armv7-linux-gnueabi -march=arm -mcpu=cortex-a8 \
+; RUN: -mattr=-neon,-vfp3,+vfp2 -arm-reserve-r9 -filetype=obj -o - \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CORTEX-A8
+; RUN: llc < %s -mtriple=armv7-linux-gnueabi -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=V7
+; RUN: llc < %s -mtriple=armv8-linux-gnueabi -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=V8
+; RUN: llc < %s -mtriple=thumbv8-linux-gnueabi -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=Vt8
+; RUN: llc < %s -mtriple=armv8-linux-gnueabi \
+; RUN: -mattr=-neon,-crypto -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=V8-FPARMv8
+; RUN: llc < %s -mtriple=armv8-linux-gnueabi \
+; RUN: -mattr=-fp-armv8,-crypto -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=V8-NEON
+; RUN: llc < %s -mtriple=armv8-linux-gnueabi \
+; RUN: -mattr=-crypto -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=V8-FPARMv8-NEON
+; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a9 -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CORTEX-A9
+; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CORTEX-A15
+; RUN: llc < %s -mtriple=thumbv6m-linux-gnueabi -mcpu=cortex-m0 -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CORTEX-M0
+; RUN: llc < %s -mtriple=thumbv7m-linux-gnueabi -mcpu=cortex-m4 -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CORTEX-M4
+; RUN: llc < %s -mtriple=armv7r-linux-gnueabi -mcpu=cortex-r5 -filetype=obj \
+; RUN: | llvm-readobj -s -sd | FileCheck %s --check-prefix=CORTEX-R5
-; This tests that the extpected ARM attributes are emitted.
-;
; BASIC: Section {
; BASIC: Name: .ARM.attributes
; BASIC-NEXT: Type: SHT_ARM_ATTRIBUTES
; BASIC-NEXT: 0010: 06010801 14011501 17031801 1901
; BASIC-NEXT: )
-; CORTEXA8: Name: .ARM.attributes
-; CORTEXA8-NEXT: Type: SHT_ARM_ATTRIBUTES
-; CORTEXA8-NEXT: Flags [ (0x0)
-; CORTEXA8-NEXT: ]
-; CORTEXA8-NEXT: Address: 0x0
-; CORTEXA8-NEXT: Offset: 0x3C
-; CORTEXA8-NEXT: Size: 47
-; CORTEXA8-NEXT: Link: 0
-; CORTEXA8-NEXT: Info: 0
-; CORTEXA8-NEXT: AddressAlignment: 1
-; CORTEXA8-NEXT: EntrySize: 0
-; CORTEXA8-NEXT: SectionData (
-; CORTEXA8-NEXT: 0000: 412E0000 00616561 62690001 24000000
-; CORTEXA8-NEXT: 0010: 05434F52 5445582D 41380006 0A074108
-; CORTEXA8-NEXT: 0020: 0109020A 02140115 01170318 011901
-; CORTEXA8-NEXT: )
+; CORTEX-A8: Name: .ARM.attributes
+; CORTEX-A8-NEXT: Type: SHT_ARM_ATTRIBUTES
+; CORTEX-A8-NEXT: Flags [ (0x0)
+; CORTEX-A8-NEXT: ]
+; CORTEX-A8-NEXT: Address: 0x0
+; CORTEX-A8-NEXT: Offset: 0x3C
+; CORTEX-A8-NEXT: Size: 47
+; CORTEX-A8-NEXT: Link: 0
+; CORTEX-A8-NEXT: Info: 0
+; CORTEX-A8-NEXT: AddressAlignment: 1
+; CORTEX-A8-NEXT: EntrySize: 0
+; CORTEX-A8-NEXT: SectionData (
+; CORTEX-A8-NEXT: 0000: 412E0000 00616561 62690001 24000000
+; CORTEX-A8-NEXT: 0010: 05434F52 5445582D 41380006 0A074108
+; CORTEX-A8-NEXT: 0020: 0109020A 02140115 01170318 011901
+; CORTEX-A8-NEXT: )
+
+; V7: Name: .ARM.attributes
+; V7-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; V7-NEXT: Flags [ (0x0)
+; V7-NEXT: ]
+; V7-NEXT: Address: 0x0
+; V7-NEXT: Offset: 0x3C
+; V7-NEXT: Size: 36
+; V7-NEXT: Link: 0
+; V7-NEXT: Info: 0
+; V7-NEXT: AddressAlignment: 1
+; V7-NEXT: EntrySize: 0
+; V7-NEXT: SectionData (
+; V7-NEXT: 0000: 41230000 00616561 62690001 19000000
+; V7-NEXT: 0010: 060A0801 09020A03 0C011401 15011703
+; V7-NEXT: 0020: 18011901
+; V7-NEXT: )
+
+; V8: Name: .ARM.attributes
+; V8-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; V8-NEXT: Flags [ (0x0)
+; V8-NEXT: ]
+; V8-NEXT: Address: 0x0
+; V8-NEXT: Offset: 0x3C
+; V8-NEXT: Size: 38
+; V8-NEXT: Link: 0
+; V8-NEXT: Info: 0
+; V8-NEXT: AddressAlignment: 1
+; V8-NEXT: EntrySize: 0
+; V8-NEXT: SectionData (
+; V8-NEXT: 0000: 41250000 00616561 62690001 1B000000
+; V8-NEXT: 0010: 060E0801 09020A07 0C031401 15011703
+; V8-NEXT: 0020: 18011901 2C02
+; V8-NEXT: )
+
+; Vt8: Name: .ARM.attributes
+; Vt8-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; Vt8-NEXT: Flags [ (0x0)
+; Vt8-NEXT: ]
+; Vt8-NEXT: Address: 0x0
+; Vt8-NEXT: Offset: 0x38
+; Vt8-NEXT: Size: 38
+; Vt8-NEXT: Link: 0
+; Vt8-NEXT: Info: 0
+; Vt8-NEXT: AddressAlignment: 1
+; Vt8-NEXT: EntrySize: 0
+; Vt8-NEXT: SectionData (
+; Vt8-NEXT: 0000: 41250000 00616561 62690001 1B000000
+; Vt8-NEXT: 0010: 060E0801 09020A07 0C031401 15011703
+; Vt8-NEXT: 0020: 18011901 2C02
+; Vt8-NEXT: )
+
+
+; V8-FPARMv8: Name: .ARM.attributes
+; V8-FPARMv8-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; V8-FPARMv8-NEXT: Flags [ (0x0)
+; V8-FPARMv8-NEXT: ]
+; V8-FPARMv8-NEXT: Address: 0x0
+; V8-FPARMv8-NEXT: Offset: 0x3C
+; V8-FPARMv8-NEXT: Size: 36
+; V8-FPARMv8-NEXT: Link: 0
+; V8-FPARMv8-NEXT: Info: 0
+; V8-FPARMv8-NEXT: AddressAlignment: 1
+; V8-FPARMv8-NEXT: EntrySize: 0
+; V8-FPARMv8-NEXT: SectionData (
+; V8-FPARMv8-NEXT: 0000: 41230000 00616561 62690001 19000000
+; V8-FPARMv8-NEXT: 0010: 060E0801 09020A07 14011501 17031801
+; V8-FPARMv8-NEXT: 0020: 19012C02
+; V8-FPARMv8-NEXT: )
+
+
+; V8-NEON: Name: .ARM.attributes
+; V8-NEON-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; V8-NEON-NEXT: Flags [ (0x0)
+; V8-NEON-NEXT: ]
+; V8-NEON-NEXT: Address: 0x0
+; V8-NEON-NEXT: Offset: 0x3C
+; V8-NEON-NEXT: Size: 38
+; V8-NEON-NEXT: Link: 0
+; V8-NEON-NEXT: Info: 0
+; V8-NEON-NEXT: AddressAlignment: 1
+; V8-NEON-NEXT: EntrySize: 0
+; V8-NEON-NEXT: SectionData (
+; V8-NEON-NEXT: 0000: 41250000 00616561 62690001 1B000000
+; V8-NEON-NEXT: 0010: 060E0801 09020A05 0C031401 15011703
+; V8-NEON-NEXT: 0020: 18011901 2C02
+; V8-NEON-NEXT: )
+
+; V8-FPARMv8-NEON: Name: .ARM.attributes
+; V8-FPARMv8-NEON-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; V8-FPARMv8-NEON-NEXT: Flags [ (0x0)
+; V8-FPARMv8-NEON-NEXT: ]
+; V8-FPARMv8-NEON-NEXT: Address: 0x0
+; V8-FPARMv8-NEON-NEXT: Offset: 0x3C
+; V8-FPARMv8-NEON-NEXT: Size: 38
+; V8-FPARMv8-NEON-NEXT: Link: 0
+; V8-FPARMv8-NEON-NEXT: Info: 0
+; V8-FPARMv8-NEON-NEXT: AddressAlignment: 1
+; V8-FPARMv8-NEON-NEXT: EntrySize: 0
+; V8-FPARMv8-NEON-NEXT: SectionData (
+; V8-FPARMv8-NEON-NEXT: 0000: 41250000 00616561 62690001 1B000000
+; V8-FPARMv8-NEON-NEXT: 0010: 060E0801 09020A07 0C031401 15011703
+; V8-FPARMv8-NEON-NEXT: 0020: 18011901 2C02
+; V8-FPARMv8-NEON-NEXT: )
+
+; CORTEX-A9: Name: .ARM.attributes
+; CORTEX-A9-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; CORTEX-A9-NEXT: Flags [ (0x0)
+; CORTEX-A9-NEXT: ]
+; CORTEX-A9-NEXT: Address: 0x0
+; CORTEX-A9-NEXT: Offset: 0x3C
+; CORTEX-A9-NEXT: Size: 49
+; CORTEX-A9-NEXT: Link: 0
+; CORTEX-A9-NEXT: Info: 0
+; CORTEX-A9-NEXT: AddressAlignment: 1
+; CORTEX-A9-NEXT: EntrySize: 0
+; CORTEX-A9-NEXT: SectionData (
+; CORTEX-A9-NEXT: 0000: 41300000 00616561 62690001 26000000
+; CORTEX-A9-NEXT: 0010: 05434F52 5445582D 41390006 0A074108
+; CORTEX-A9-NEXT: 0020: 0109020A 030C0114 01150117 03180119
+; CORTEX-A9-NEXT: 0030: 01
+; CORTEX-A9-NEXT: )
+
+; CORTEX-A15: Name: .ARM.attributes
+; CORTEX-A15-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; CORTEX-A15-NEXT: Flags [ (0x0)
+; CORTEX-A15-NEXT: ]
+; CORTEX-A15-NEXT: Address: 0x0
+; CORTEX-A15-NEXT: Offset: 0x3C
+; CORTEX-A15-NEXT: Size: 52
+; CORTEX-A15-NEXT: Link: 0
+; CORTEX-A15-NEXT: Info: 0
+; CORTEX-A15-NEXT: AddressAlignment: 1
+; CORTEX-A15-NEXT: EntrySize: 0
+; CORTEX-A15-NEXT: SectionData (
+; CORTEX-A15-NEXT: 0000: 41330000 00616561 62690001 29000000
+; CORTEX-A15-NEXT: 0010: 05434F52 5445582D 41313500 060A0741
+; CORTEX-A15-NEXT: 0020: 08010902 0A050C02 14011501 17031801
+; CORTEX-A15-NEXT: 0030: 19012C02
+; CORTEX-A15-NEXT: )
+
+; CORTEX-M0: Name: .ARM.attributes
+; CORTEX-M0-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; CORTEX-M0-NEXT: Flags [ (0x0)
+; CORTEX-M0-NEXT: ]
+; CORTEX-M0-NEXT: Address: 0x0
+; CORTEX-M0-NEXT: Offset: 0x38
+; CORTEX-M0-NEXT: Size: 45
+; CORTEX-M0-NEXT: Link: 0
+; CORTEX-M0-NEXT: Info: 0
+; CORTEX-M0-NEXT: AddressAlignment: 1
+; CORTEX-M0-NEXT: EntrySize: 0
+; CORTEX-M0-NEXT: SectionData (
+; CORTEX-M0-NEXT: 0000: 412C0000 00616561 62690001 22000000
+; CORTEX-M0-NEXT: 0010: 05434F52 5445582D 4D300006 0C074D08
+; CORTEX-M0-NEXT: 0020: 00090114 01150117 03180119 01
+; CORTEX-M0-NEXT: )
+
+; CORTEX-M4: Name: .ARM.attributes
+; CORTEX-M4-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; CORTEX-M4-NEXT: Flags [ (0x0)
+; CORTEX-M4-NEXT: ]
+; CORTEX-M4-NEXT: Address: 0x0
+; CORTEX-M4-NEXT: Offset: 0x38
+; CORTEX-M4-NEXT: Size: 49
+; CORTEX-M4-NEXT: Link: 0
+; CORTEX-M4-NEXT: Info: 0
+; CORTEX-M4-NEXT: AddressAlignment: 1
+; CORTEX-M4-NEXT: EntrySize: 0
+; CORTEX-M4-NEXT: SectionData (
+; CORTEX-M4-NEXT: 0000: 41300000 00616561 62690001 26000000
+; CORTEX-M4-NEXT: 0010: 05434F52 5445582D 4D340006 0D074D08
+; CORTEX-M4-NEXT: 0020: 0009020A 06140115 01170318 0119012C
+; CORTEX-M4-NEXT: 0030: 00
+; CORTEX-M4-NEXT: )
+
+; CORTEX-R5: Name: .ARM.attributes
+; CORTEX-R5-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+; CORTEX-R5-NEXT: Flags [ (0x0)
+; CORTEX-R5-NEXT: ]
+; CORTEX-R5-NEXT: Address: 0x0
+; CORTEX-R5-NEXT: Offset: 0x3C
+; CORTEX-R5-NEXT: Size: 49
+; CORTEX-R5-NEXT: Link: 0
+; CORTEX-R5-NEXT: Info: 0
+; CORTEX-R5-NEXT: AddressAlignment: 1
+; CORTEX-R5-NEXT: EntrySize: 0
+; CORTEX-R5-NEXT: SectionData (
+; CORTEX-R5-NEXT: 0000: 41300000 00616561 62690001 26000000
+; CORTEX-R5-NEXT: 0010: 05434F52 5445582D 52350006 0A075208
+; CORTEX-R5-NEXT: 0020: 0109020A 04140115 01170318 0119012C
+; CORTEX-R5-NEXT: 0030: 02
+; CORTEX-R5-NEXT: )
define i32 @f(i64 %z) {
ret i32 0
--- /dev/null
+@ RUN: llvm-mc < %s -triple armv7-unknown-linux-gnueabi -filetype=obj -o - \
+@ RUN: | llvm-readobj -s -sd | FileCheck %s
+
+@ CHECK: Name: .ARM.attribute
+@ CHECK: SectionData (
+
+@ <format-version>
+@ CHECK: 41
+
+@ <section-length>
+@ CHECK: 1A0000 00
+
+@ <vendor-name> "aeabi\0"
+@ CHECK: 616561 626900
+
+@ <file-tag>
+@ CHECK: 01
+
+@ <size>
+@ CHECK: 10000000
+
+ .cpu cortex-a8
+@ CHECK: 05
+@ CHECK: 434F52 5445582D 413800
+
+@ CHECK: )
--- /dev/null
+@ RUN: llvm-mc < %s -triple armv7-unknown-linux-gnueabi -filetype=obj -o - \
+@ RUN: | llvm-readobj -s -sd | FileCheck %s
+
+@ CHECK: Name: .ARM.attribute
+@ CHECK: SectionData (
+
+@ <format-version>
+@ CHECK: 41
+
+@ <section-length>
+@ CHECK: 250000 00
+
+@ <vendor-name> "aeabi\0"
+@ CHECK: 616561 626900
+
+@ <file-tag>
+@ CHECK: 01
+
+@ <size>
+@ CHECK: 1B000000
+
+@ <attribute>*
+
+ .eabi_attribute 6, 10
+@ CHECK: 060A
+
+ .eabi_attribute 7, 65
+@ CHECK: 0741
+
+ .eabi_attribute 8, 1
+@ CHECK: 0801
+
+ .eabi_attribute 9, 2
+@ CHECK: 0902
+
+ .eabi_attribute 10, 3
+@ CHECK: 0A03
+
+ .eabi_attribute 12, 1
+@ CHECK: 0C01
+
+ .eabi_attribute 20, 1
+@ CHECK: 1401
+
+ .eabi_attribute 21, 1
+@ CHECK: 1501
+
+ .eabi_attribute 23, 3
+@ CHECK: 1703
+
+ .eabi_attribute 24, 1
+@ CHECK: 1801
+
+ .eabi_attribute 25, 1
+@ CHECK: 1901
+@ CHECK: )
--- /dev/null
+@ Check multiple .fpu directives.
+
+@ The later .fpu directive should overwrite the earlier one.
+@ See also: directive-fpu-multiple2.s.
+
+@ RUN: llvm-mc < %s -triple arm-unknown-linux-gnueabi -filetype=obj \
+@ RUN: | llvm-readobj -s -sd | FileCheck %s
+
+ .fpu neon
+ .fpu vfpv4
+
+@ CHECK: Name: .ARM.attributes
+@ CHECK-NEXT: Type: SHT_ARM_ATTRIBUTES (0x70000003)
+@ CHECK-NEXT: Flags [ (0x0)
+@ CHECK-NEXT: ]
+@ CHECK-NEXT: Address: 0x0
+@ CHECK-NEXT: Offset: 0x34
+@ CHECK-NEXT: Size: 18
+@ CHECK-NEXT: Link: 0
+@ CHECK-NEXT: Info: 0
+@ CHECK-NEXT: AddressAlignment: 1
+@ CHECK-NEXT: EntrySize: 0
+@ CHECK-NEXT: SectionData (
+@ CHECK-NEXT: 0000: 41110000 00616561 62690001 07000000
+@ CHECK-NEXT: 0010: 0A05
+@ CHECK-NEXT: )
--- /dev/null
+@ RUN: llvm-mc < %s -triple armv7-unknown-linux-gnueabi -filetype=obj -o - \
+@ RUN: | llvm-readobj -s -sd | FileCheck %s
+
+@ CHECK: Name: .ARM.attribute
+@ CHECK: SectionData (
+
+@ <format-version>
+@ CHECK: 41
+
+@ <section-length>
+@ CHECK: 130000 00
+
+@ <vendor-name> "aeabi\0"
+@ CHECK: 616561 626900
+
+@ <file-tag>
+@ CHECK: 01
+
+@ <size>
+@ CHECK: 09000000
+
+ .fpu neon
+@ CHECK: 0A03
+@ CHECK: 0C01
+
+@ CHECK: )