Changeset View
Changeset View
Standalone View
Standalone View
head/devel/llvm60/files/lld/patch-head-r336972.diff
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
r336972 | emaste | 2018-07-31 17:25:03 +0200 (Tue, 31 Jul 2018) | 37 lines | |||||
lld: [ELF][ARM] Implement support for Tag_ABI_VFP_args | |||||
The Tag_ABI_VFP_args build attribute controls the procedure call | |||||
standard used for floating point parameters on ARM. The values are: | |||||
0 - Base AAPCS (FP Parameters passed in Core (Integer) registers | |||||
1 - VFP AAPCS (FP Parameters passed in FP registers) | |||||
2 - Toolchain specific (Neither Base or VFP) | |||||
3 - Compatible with all (No use of floating point parameters) | |||||
If the Tag_ABI_VFP_args build attribute is missing it has an implicit | |||||
value of 0. | |||||
We use the attribute in two ways: | |||||
* Detect a clash in calling convention between Base, VFP and Toolchain. | |||||
we follow ld.bfd's lead and do not error if there is a clash between an | |||||
implicit Base AAPCS caused by a missing attribute. Many projects | |||||
including the hard-float (VFP AAPCS) version of glibc contain assembler | |||||
files that do not use floating point but do not have Tag_ABI_VFP_args. | |||||
* Set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD ELF header flag | |||||
for Base or VFP AAPCS respectively. This flag is used by some ELF | |||||
loaders. | |||||
References: | |||||
* Addenda to, and Errata in, the ABI for the ARM Architecture for | |||||
Tag_ABI_VFP_args | |||||
* Elf for the ARM Architecture for ELF header flags | |||||
Fixes LLVM PR36009 | |||||
PR: 229050 | |||||
Obtained from: llvm r338377 by Peter Smith | |||||
Index: tools/lld/ELF/Arch/ARM.cpp | |||||
=================================================================== | |||||
--- tools/lld/ELF/Arch/ARM.cpp (revision 336971) | |||||
+++ tools/lld/ELF/Arch/ARM.cpp (revision 336972) | |||||
@@ -97,10 +97,19 @@ ARM::ARM() { | |||||
} | |||||
uint32_t ARM::calcEFlags() const { | |||||
+ // The ABIFloatType is used by loaders to detect the floating point calling | |||||
+ // convention. | |||||
+ uint32_t ABIFloatType = 0; | |||||
+ if (Config->ARMVFPArgs == ARMVFPArgKind::Base || | |||||
+ Config->ARMVFPArgs == ARMVFPArgKind::Default) | |||||
+ ABIFloatType = EF_ARM_ABI_FLOAT_SOFT; | |||||
+ else if (Config->ARMVFPArgs == ARMVFPArgKind::VFP) | |||||
+ ABIFloatType = EF_ARM_ABI_FLOAT_HARD; | |||||
+ | |||||
// We don't currently use any features incompatible with EF_ARM_EABI_VER5, | |||||
// but we don't have any firm guarantees of conformance. Linux AArch64 | |||||
// kernels (as of 2016) require an EABI version to be set. | |||||
- return EF_ARM_EABI_VER5; | |||||
+ return EF_ARM_EABI_VER5 | ABIFloatType; | |||||
} | |||||
RelExpr ARM::getRelExpr(RelType Type, const Symbol &S, | |||||
Index: tools/lld/ELF/Config.h | |||||
=================================================================== | |||||
--- tools/lld/ELF/Config.h (revision 336971) | |||||
+++ tools/lld/ELF/Config.h (revision 336972) | |||||
@@ -54,6 +54,9 @@ enum class SortSectionPolicy { Default, None, Alig | |||||
// For --target2 | |||||
enum class Target2Policy { Abs, Rel, GotRel }; | |||||
+// For tracking ARM Float Argument PCS | |||||
+enum class ARMVFPArgKind { Default, Base, VFP, ToolChain }; | |||||
+ | |||||
struct SymbolVersion { | |||||
llvm::StringRef Name; | |||||
bool IsExternCpp; | |||||
@@ -169,6 +172,7 @@ struct Configuration { | |||||
StripPolicy Strip; | |||||
UnresolvedPolicy UnresolvedSymbols; | |||||
Target2Policy Target2; | |||||
+ ARMVFPArgKind ARMVFPArgs = ARMVFPArgKind::Default; | |||||
BuildIdKind BuildId = BuildIdKind::None; | |||||
ELFKind EKind = ELFNoneKind; | |||||
uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; | |||||
Index: tools/lld/ELF/InputFiles.cpp | |||||
=================================================================== | |||||
--- tools/lld/ELF/InputFiles.cpp (revision 336971) | |||||
+++ tools/lld/ELF/InputFiles.cpp (revision 336972) | |||||
@@ -441,6 +441,46 @@ void ObjFile<ELFT>::initializeSections( | |||||
} | |||||
} | |||||
+// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD | |||||
+// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how | |||||
+// the input objects have been compiled. | |||||
+static void updateARMVFPArgs(const ARMAttributeParser &Attributes, | |||||
+ const InputFile *F) { | |||||
+ if (!Attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args)) | |||||
+ // If an ABI tag isn't present then it is implicitly given the value of 0 | |||||
+ // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files, | |||||
+ // including some in glibc that don't use FP args (and should have value 3) | |||||
+ // don't have the attribute so we do not consider an implicit value of 0 | |||||
+ // as a clash. | |||||
+ return; | |||||
+ | |||||
+ unsigned VFPArgs = Attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args); | |||||
+ ARMVFPArgKind Arg; | |||||
+ switch (VFPArgs) { | |||||
+ case ARMBuildAttrs::BaseAAPCS: | |||||
+ Arg = ARMVFPArgKind::Base; | |||||
+ break; | |||||
+ case ARMBuildAttrs::HardFPAAPCS: | |||||
+ Arg = ARMVFPArgKind::VFP; | |||||
+ break; | |||||
+ case ARMBuildAttrs::ToolChainFPPCS: | |||||
+ // Tool chain specific convention that conforms to neither AAPCS variant. | |||||
+ Arg = ARMVFPArgKind::ToolChain; | |||||
+ break; | |||||
+ case ARMBuildAttrs::CompatibleFPAAPCS: | |||||
+ // Object compatible with all conventions. | |||||
+ return; | |||||
+ default: | |||||
+ error(toString(F) + ": unknown Tag_ABI_VFP_args value: " + Twine(VFPArgs)); | |||||
+ return; | |||||
+ } | |||||
+ // Follow ld.bfd and error if there is a mix of calling conventions. | |||||
+ if (Config->ARMVFPArgs != Arg && Config->ARMVFPArgs != ARMVFPArgKind::Default) | |||||
+ error(toString(F) + ": incompatible Tag_ABI_VFP_args"); | |||||
+ else | |||||
+ Config->ARMVFPArgs = Arg; | |||||
+} | |||||
+ | |||||
// The ARM support in lld makes some use of instructions that are not available | |||||
// on all ARM architectures. Namely: | |||||
// - Use of BLX instruction for interworking between ARM and Thumb state. | |||||
@@ -520,6 +560,8 @@ InputSectionBase *ObjFile<ELFT>::createInputSectio | |||||
ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec)); | |||||
Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind); | |||||
updateSupportedARMFeatures(Attributes); | |||||
+ updateARMVFPArgs(Attributes, this); | |||||
+ | |||||
// FIXME: Retain the first attribute section we see. The eglibc ARM | |||||
// dynamic loaders require the presence of an attribute section for dlopen | |||||
// to work. In a full implementation we would merge all attribute sections. |