From 23125d02d929758e1b0dbb30b13f1deff7a5ea4b Mon Sep 17 00:00:00 2001 From: Logan Chien Date: Mon, 28 Oct 2013 17:51:12 +0000 Subject: [PATCH] [arm] Implement eabi_attribute, cpu, and fpu directives. This commit allows the ARM integrated assembler to parse and assemble the code with .eabi_attribute, .cpu, and .fpu directives. To implement the feature, this commit moves the code from AttrEmitter to ARMTargetStreamers, and several new test cases related to cortex-m4, cortex-r5, and cortex-a15 are added. Besides, this commit also change the Subtarget->isFPOnlySP() to Subtarget->hasD16() to match the usage of .fpu directive. This commit changes the test cases: * Several .eabi_attribute directives in 2010-09-29-mc-asm-header-test.ll are removed because the .fpu directive already cover the functionality. * In the Cortex-A15 test case, the value for Tag_Advanced_SIMD_arch has be changed from 1 to 2, which is more precise. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193524 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCStreamer.h | 6 + lib/Target/ARM/ARM.td | 5 +- lib/Target/ARM/ARMAsmPrinter.cpp | 302 +++------------- lib/Target/ARM/ARMBuildAttrs.h | 30 +- lib/Target/ARM/ARMFPUName.def | 32 ++ lib/Target/ARM/ARMFPUName.h | 26 ++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 51 ++- .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 333 ++++++++++++++++++ .../ARM/2010-09-29-mc-asm-header-test.ll | 33 +- .../ARM/2010-10-19-mc-elf-objheader.ll | 264 ++++++++++++-- test/MC/ARM/directive-cpu.s | 26 ++ test/MC/ARM/directive-eabi_attribute.s | 56 +++ test/MC/ARM/directive-fpu-multiple.s | 26 ++ test/MC/ARM/directive-fpu.s | 26 ++ 14 files changed, 913 insertions(+), 303 deletions(-) create mode 100644 lib/Target/ARM/ARMFPUName.def create mode 100644 lib/Target/ARM/ARMFPUName.h create mode 100644 test/MC/ARM/directive-cpu.s create mode 100644 test/MC/ARM/directive-eabi_attribute.s create mode 100644 test/MC/ARM/directive-fpu-multiple.s create mode 100644 test/MC/ARM/directive-fpu.s diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 47d798dd8bd..04af407a445 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -87,6 +87,12 @@ public: virtual void emitPad(int64_t Offset) = 0; virtual void emitRegSave(const SmallVectorImpl &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 diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td index a0592f23d35..bf12c323fa6 100644 --- a/lib/Target/ARM/ARM.td +++ b/lib/Target/ARM/ARM.td @@ -309,7 +309,7 @@ def : ProcessorModel<"cortex-r5", CortexA8Model, [ProcR5, HasV7Ops, FeatureDB, FeatureVFP3, FeatureDSPThumb2, FeatureHasRAS, FeatureVFPOnlySP, - FeatureRClass]>; + FeatureD16, FeatureRClass]>; // V7M Processors. def : ProcNoItin<"cortex-m3", [HasV7Ops, @@ -321,7 +321,8 @@ def : ProcNoItin<"cortex-m4", [HasV7Ops, FeatureThumb2, FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, FeatureT2XtPk, FeatureVFP4, - FeatureVFPOnlySP, FeatureMClass]>; + FeatureVFPOnlySP, FeatureD16, + FeatureMClass]>; // Swift uArch Processors. def : ProcessorModel<"swift", SwiftModel, diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 4899a5deceb..d1f1d3ed1bb 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -17,6 +17,7 @@ #include "ARM.h" #include "ARMBuildAttrs.h" #include "ARMConstantPoolValue.h" +#include "ARMFPUName.h" #include "ARMMachineFunctionInfo.h" #include "ARMTargetMachine.h" #include "ARMTargetObjectFile.h" @@ -55,164 +56,6 @@ #include 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 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(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(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() { diff --git a/lib/Target/ARM/ARMBuildAttrs.h b/lib/Target/ARM/ARMBuildAttrs.h index 44fbf3d0c96..93edc55d51f 100644 --- a/lib/Target/ARM/ARMBuildAttrs.h +++ b/lib/Target/ARM/ARMBuildAttrs.h @@ -15,11 +15,13 @@ #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 { @@ -93,7 +95,7 @@ namespace ARMBuildAttrs { 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) @@ -102,40 +104,50 @@ namespace ARMBuildAttrs { }; // 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__ diff --git a/lib/Target/ARM/ARMFPUName.def b/lib/Target/ARM/ARMFPUName.def new file mode 100644 index 00000000000..9a1bbe703d9 --- /dev/null +++ b/lib/Target/ARM/ARMFPUName.def @@ -0,0 +1,32 @@ +//===-- 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 diff --git a/lib/Target/ARM/ARMFPUName.h b/lib/Target/ARM/ARMFPUName.h new file mode 100644 index 00000000000..2a64cce4880 --- /dev/null +++ b/lib/Target/ARM/ARMFPUName.h @@ -0,0 +1,26 @@ +//===-- 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 diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index ed71b37b471..ba6075e91df 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "ARMBuildAttrs.h" +#include "ARMFPUName.h" #include "ARMFeatures.h" #include "llvm/MC/MCTargetAsmParser.h" #include "MCTargetDesc/ARMAddressingModes.h" @@ -137,6 +139,8 @@ class ARMAsmParser : public MCTargetAsmParser { 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); @@ -7765,6 +7769,10 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { 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") @@ -7987,7 +7995,48 @@ bool ARMAsmParser::parseDirectiveArch(SMLoc L) { /// 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(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 diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index d4110a45d66..471897de5c1 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -13,6 +13,8 @@ // //===----------------------------------------------------------------------===// +#include "ARMBuildAttrs.h" +#include "ARMFPUName.h" #include "ARMRegisterInfo.h" #include "ARMUnwindOp.h" #include "ARMUnwindOpAsm.h" @@ -39,6 +41,7 @@ #include "llvm/Support/ELF.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" +#include using namespace llvm; @@ -47,6 +50,17 @@ static std::string GetAEABIUnwindPersonalityName(unsigned Index) { 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; @@ -65,6 +79,12 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer { virtual void emitRegSave(const SmallVectorImpl &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); }; @@ -109,9 +129,114 @@ void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl &RegList, 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 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(); @@ -121,6 +246,20 @@ class ARMTargetELFStreamer : public ARMTargetStreamer { virtual void emitPad(int64_t Offset); virtual void emitRegSave(const SmallVectorImpl &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 @@ -149,6 +288,8 @@ public: ~ARMELFStreamer() {} + virtual void FinishImpl(); + // ARM exception handling directives void emitFnStart(); void emitFnEnd(); @@ -329,6 +470,198 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl &RegList, 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() { + // + // [ "vendor-name" + // [ * + // | * 0 * + // | * 0 * + // ]+ + // ]* + + 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(TS); + ATS.finishAttributeSection(); + + MCELFStreamer::FinishImpl(); +} inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, unsigned Type, diff --git a/test/CodeGen/ARM/2010-09-29-mc-asm-header-test.ll b/test/CodeGen/ARM/2010-09-29-mc-asm-header-test.ll index e9e9def8d3b..925d0cd3668 100644 --- a/test/CodeGen/ARM/2010-09-29-mc-asm-header-test.ll +++ b/test/CodeGen/ARM/2010-09-29-mc-asm-header-test.ll @@ -1,3 +1,6 @@ +; 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 @@ -10,13 +13,12 @@ ; 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 @@ -34,7 +36,6 @@ ; 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 @@ -66,7 +67,6 @@ ; 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 @@ -77,13 +77,11 @@ ; 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 @@ -92,14 +90,25 @@ ; 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 @@ -113,8 +122,7 @@ ; 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 @@ -127,8 +135,7 @@ ; 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 @@ -142,7 +149,6 @@ ; 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 @@ -154,7 +160,6 @@ ; 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 diff --git a/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll b/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll index 09246917e26..4efccabf0cb 100644 --- a/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll +++ b/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll @@ -1,13 +1,36 @@ -; 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 @@ -25,22 +48,215 @@ ; 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 diff --git a/test/MC/ARM/directive-cpu.s b/test/MC/ARM/directive-cpu.s new file mode 100644 index 00000000000..952dd93f370 --- /dev/null +++ b/test/MC/ARM/directive-cpu.s @@ -0,0 +1,26 @@ +@ 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 ( + +@ +@ CHECK: 41 + +@ +@ CHECK: 1A0000 00 + +@ "aeabi\0" +@ CHECK: 616561 626900 + +@ +@ CHECK: 01 + +@ +@ CHECK: 10000000 + + .cpu cortex-a8 +@ CHECK: 05 +@ CHECK: 434F52 5445582D 413800 + +@ CHECK: ) diff --git a/test/MC/ARM/directive-eabi_attribute.s b/test/MC/ARM/directive-eabi_attribute.s new file mode 100644 index 00000000000..c060b809c84 --- /dev/null +++ b/test/MC/ARM/directive-eabi_attribute.s @@ -0,0 +1,56 @@ +@ 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 ( + +@ +@ CHECK: 41 + +@ +@ CHECK: 250000 00 + +@ "aeabi\0" +@ CHECK: 616561 626900 + +@ +@ CHECK: 01 + +@ +@ CHECK: 1B000000 + +@ * + + .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: ) diff --git a/test/MC/ARM/directive-fpu-multiple.s b/test/MC/ARM/directive-fpu-multiple.s new file mode 100644 index 00000000000..6a93f246822 --- /dev/null +++ b/test/MC/ARM/directive-fpu-multiple.s @@ -0,0 +1,26 @@ +@ 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: ) diff --git a/test/MC/ARM/directive-fpu.s b/test/MC/ARM/directive-fpu.s new file mode 100644 index 00000000000..24e159c74fc --- /dev/null +++ b/test/MC/ARM/directive-fpu.s @@ -0,0 +1,26 @@ +@ 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 ( + +@ +@ CHECK: 41 + +@ +@ CHECK: 130000 00 + +@ "aeabi\0" +@ CHECK: 616561 626900 + +@ +@ CHECK: 01 + +@ +@ CHECK: 09000000 + + .fpu neon +@ CHECK: 0A03 +@ CHECK: 0C01 + +@ CHECK: )