[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
This commit is contained in:
Logan Chien 2013-10-28 17:51:12 +00:00
parent 790b973f80
commit 23125d02d9
14 changed files with 913 additions and 303 deletions

View File

@ -87,6 +87,12 @@ public:
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

View File

@ -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,

View File

@ -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 <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 {
@ -768,149 +611,102 @@ static ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU,
}
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() {

View File

@ -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__

View File

@ -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

View File

@ -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

View File

@ -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<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

View File

@ -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 <algorithm>
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<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);
};
@ -109,9 +129,114 @@ void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &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<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();
@ -121,6 +246,20 @@ class ARMTargetELFStreamer : public ARMTargetStreamer {
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
@ -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<unsigned> &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() {
// <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,

View File

@ -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

View File

@ -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

View File

@ -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 (
@ <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: )

View File

@ -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 (
@ <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: )

View File

@ -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: )

View File

@ -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 (
@ <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: )