Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -74,6 +74,10 @@ SubtargetFeatures getFeatures() const override; + SubtargetFeatures getMIPSFeatures() const override; + + SubtargetFeatures getARMFeatures() const override; + void setARMSubArch(Triple &TheTriple) const override; }; Index: include/llvm/Object/ObjectFile.h =================================================================== --- include/llvm/Object/ObjectFile.h +++ include/llvm/Object/ObjectFile.h @@ -267,6 +267,8 @@ virtual StringRef getFileFormatName() const = 0; virtual /* Triple::ArchType */ unsigned getArch() const = 0; virtual SubtargetFeatures getFeatures() const = 0; + virtual SubtargetFeatures getMIPSFeatures() const { return SubtargetFeatures(); } + virtual SubtargetFeatures getARMFeatures() const { return SubtargetFeatures(); } virtual void setARMSubArch(Triple &TheTriple) const { } /// Returns platform-specific object flags, if any. Index: include/llvm/Support/ARMAttributeParser.h =================================================================== --- include/llvm/Support/ARMAttributeParser.h +++ include/llvm/Support/ARMAttributeParser.h @@ -125,6 +125,10 @@ void Parse(ArrayRef Section, bool isLittle); + bool hasAttribute(unsigned Tag) const { + return Attributes.count(Tag); + } + unsigned getAttributeValue(unsigned Tag) const { return Attributes.find(Tag)->second.first; } Index: lib/Object/ELFObjectFile.cpp =================================================================== --- lib/Object/ELFObjectFile.cpp +++ lib/Object/ELFObjectFile.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/MathExtras.h" namespace llvm { @@ -55,68 +57,139 @@ return std::move(R); } -SubtargetFeatures ELFObjectFileBase::getFeatures() const { - switch (getEMachine()) { - case ELF::EM_MIPS: { - SubtargetFeatures Features; - unsigned PlatformFlags; - getPlatformFlags(PlatformFlags); +SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const { + SubtargetFeatures Features; + unsigned PlatformFlags; + getPlatformFlags(PlatformFlags); - switch (PlatformFlags & ELF::EF_MIPS_ARCH) { - case ELF::EF_MIPS_ARCH_1: - break; - case ELF::EF_MIPS_ARCH_2: - Features.AddFeature("mips2"); - break; - case ELF::EF_MIPS_ARCH_3: - Features.AddFeature("mips3"); - break; - case ELF::EF_MIPS_ARCH_4: - Features.AddFeature("mips4"); - break; - case ELF::EF_MIPS_ARCH_5: - Features.AddFeature("mips5"); - break; - case ELF::EF_MIPS_ARCH_32: - Features.AddFeature("mips32"); + switch (PlatformFlags & ELF::EF_MIPS_ARCH) { + case ELF::EF_MIPS_ARCH_1: + break; + case ELF::EF_MIPS_ARCH_2: + Features.AddFeature("mips2"); + break; + case ELF::EF_MIPS_ARCH_3: + Features.AddFeature("mips3"); + break; + case ELF::EF_MIPS_ARCH_4: + Features.AddFeature("mips4"); + break; + case ELF::EF_MIPS_ARCH_5: + Features.AddFeature("mips5"); + break; + case ELF::EF_MIPS_ARCH_32: + Features.AddFeature("mips32"); + break; + case ELF::EF_MIPS_ARCH_64: + Features.AddFeature("mips64"); + break; + case ELF::EF_MIPS_ARCH_32R2: + Features.AddFeature("mips32r2"); + break; + case ELF::EF_MIPS_ARCH_64R2: + Features.AddFeature("mips64r2"); + break; + case ELF::EF_MIPS_ARCH_32R6: + Features.AddFeature("mips32r6"); + break; + case ELF::EF_MIPS_ARCH_64R6: + Features.AddFeature("mips64r6"); + break; + default: + llvm_unreachable("Unknown EF_MIPS_ARCH value"); + } + + switch (PlatformFlags & ELF::EF_MIPS_MACH) { + case ELF::EF_MIPS_MACH_NONE: + // No feature associated with this value. + break; + case ELF::EF_MIPS_MACH_OCTEON: + Features.AddFeature("cnmips"); + break; + default: + llvm_unreachable("Unknown EF_MIPS_ARCH value"); + } + + if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) + Features.AddFeature("mips16"); + if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) + Features.AddFeature("micromips"); + + return Features; +} + +SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { + SubtargetFeatures Features; + ARMAttributeParser Attributes; + std::error_code EC = getBuildAttributes(Attributes); + if (EC) + return SubtargetFeatures(); + + if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) { + switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) { + case ARMBuildAttrs::ApplicationProfile: + Features.AddFeature("aclass"); break; - case ELF::EF_MIPS_ARCH_64: - Features.AddFeature("mips64"); + case ARMBuildAttrs::RealTimeProfile: + Features.AddFeature("rclass"); break; - case ELF::EF_MIPS_ARCH_32R2: - Features.AddFeature("mips32r2"); + case ARMBuildAttrs::MicroControllerProfile: + Features.AddFeature("mclass"); break; - case ELF::EF_MIPS_ARCH_64R2: - Features.AddFeature("mips64r2"); + } + } + + if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use) && + (Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use) == + ARMBuildAttrs::AllowThumb32)) + Features.AddFeature("thumb2"); + + if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) { + switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) { + case ARMBuildAttrs::AllowFPv2: + Features.AddFeature("vfp2"); break; - case ELF::EF_MIPS_ARCH_32R6: - Features.AddFeature("mips32r6"); + case ARMBuildAttrs::AllowFPv3A: + case ARMBuildAttrs::AllowFPv3B: + Features.AddFeature("vfp3"); break; - case ELF::EF_MIPS_ARCH_64R6: - Features.AddFeature("mips64r6"); + case ARMBuildAttrs::AllowFPv4A: + case ARMBuildAttrs::AllowFPv4B: + Features.AddFeature("vfp4"); break; - default: - llvm_unreachable("Unknown EF_MIPS_ARCH value"); } + } - switch (PlatformFlags & ELF::EF_MIPS_MACH) { - case ELF::EF_MIPS_MACH_NONE: - // No feature associated with this value. + if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) { + switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) { + default: break; - case ELF::EF_MIPS_MACH_OCTEON: - Features.AddFeature("cnmips"); + case ARMBuildAttrs::AllowNeon: + Features.AddFeature("neon"); + break; + case ARMBuildAttrs::AllowNeon2: + Features.AddFeature("neon"); + Features.AddFeature("fp16"); break; - default: - llvm_unreachable("Unknown EF_MIPS_ARCH value"); } + } - if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) - Features.AddFeature("mips16"); - if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) - Features.AddFeature("micromips"); - - return Features; + if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use) && + (Attributes.getAttributeValue(ARMBuildAttrs::DIV_use) == + ARMBuildAttrs::AllowDIVExt)) { + Features.AddFeature("hwdiv"); + Features.AddFeature("hwdiv-arm"); } + + return Features; +} + +SubtargetFeatures ELFObjectFileBase::getFeatures() const { + switch (getEMachine()) { + case ELF::EM_MIPS: + return getMIPSFeatures(); + case ELF::EM_ARM: + return getARMFeatures(); default: return SubtargetFeatures(); } @@ -128,6 +201,8 @@ ARMAttributeParser Attributes; std::error_code EC = getBuildAttributes(Attributes); + if (EC) + return; std::string Triple; // Default to ARM, but use the triple if it's been set. Index: test/tools/llvm-objdump/ARM/v6-subfeatures.s =================================================================== --- /dev/null +++ test/tools/llvm-objdump/ARM/v6-subfeatures.s @@ -0,0 +1,9 @@ +@ RUN: llvm-mc < %s -triple armv6 -mattr=+vfp2 -filetype=obj | llvm-objdump -triple=arm -d - | FileCheck %s + +.eabi_attribute Tag_FP_arch, 2 // VFP2 + +vfp2: + vadd.f32 s0, s1, s2 + +@CHECK-LABEL: vfp2 +@CHECK: 81 0a 30 ee vadd.f32 s0, s1, s2 Index: test/tools/llvm-objdump/ARM/v7a-subfeature.s =================================================================== --- /dev/null +++ test/tools/llvm-objdump/ARM/v7a-subfeature.s @@ -0,0 +1,36 @@ +@ RUN: llvm-mc < %s -triple armv7a -mattr=+vfp3,+neon,+fp16,+hwdiv-arm -filetype=obj | llvm-objdump -triple=arm -d - | FileCheck %s + +.eabi_attribute Tag_FP_arch, 3 // VFP3 +.eabi_attribute Tag_Advanced_SIMD_arch, 2 // SIMDv1 with fp16 +.eabi_attribute Tag_DIV_use, 2 // permitted + +vfp2: + vmla.f32 s0, s1, s2 + +@CHECK-LABEL: vfp2 +@CHECK: 81 0a 00 ee vmla.f32 s0, s1, s2 + +vfp3: + vmov.f32 s0, #0.5 + +@CHECK-LABEL: vfp3 +@CHECK: 00 0a b6 ee vmov.f32 s0, #5.000000e-01 + +neon: + vmla.f32 d0, d1, d2 + +@CHECK-LABEL: neon +@CHECK: 12 0d 01 f2 vmla.f32 d0, d1, d2 + +fp16: + vcvt.f32.f16 q0, d2 + +@CHECK-LABEL: fp16 +@CHECK: 02 07 b6 f3 vcvt.f32.f16 q0, d2 + +div: + udiv r0, r1, r2 + +@CHECK-LABEL: div +@CHECK: 11 f2 30 e7 udiv r0, r1, r2 + Index: test/tools/llvm-objdump/ARM/v7m-subfeatures.s =================================================================== --- /dev/null +++ test/tools/llvm-objdump/ARM/v7m-subfeatures.s @@ -0,0 +1,10 @@ +@ RUN: llvm-mc < %s -triple armv7m -mattr=+vfp4 -filetype=obj | llvm-objdump -triple=thumb -d - | FileCheck %s + +.eabi_attribute Tag_FP_arch, 5 // VFP4 + +.thumb +vfp4: + vmov.f32 s0, #0.5 + +@CHECK-LABEL: vfp4 +@CHECK: b6 ee 00 0a vmov.f32 s0, #5.000000e-01