Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Jul 2018 15:25:03 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r336972 - in head/contrib/llvm/tools/lld/ELF: . Arch
Message-ID:  <201807311525.w6VFP3vm058210@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Tue Jul 31 15:25:03 2018
New Revision: 336972
URL: https://svnweb.freebsd.org/changeset/base/336972

Log:
  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

Modified:
  head/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp
  head/contrib/llvm/tools/lld/ELF/Config.h
  head/contrib/llvm/tools/lld/ELF/InputFiles.cpp

Modified: head/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp
==============================================================================
--- head/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp	Tue Jul 31 15:08:02 2018	(r336971)
+++ head/contrib/llvm/tools/lld/ELF/Arch/ARM.cpp	Tue Jul 31 15:25:03 2018	(r336972)
@@ -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,

Modified: head/contrib/llvm/tools/lld/ELF/Config.h
==============================================================================
--- head/contrib/llvm/tools/lld/ELF/Config.h	Tue Jul 31 15:08:02 2018	(r336971)
+++ head/contrib/llvm/tools/lld/ELF/Config.h	Tue Jul 31 15:25:03 2018	(r336972)
@@ -54,6 +54,9 @@ enum class SortSectionPolicy { Default, None, Alignmen
 // 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;

Modified: head/contrib/llvm/tools/lld/ELF/InputFiles.cpp
==============================================================================
--- head/contrib/llvm/tools/lld/ELF/InputFiles.cpp	Tue Jul 31 15:08:02 2018	(r336971)
+++ head/contrib/llvm/tools/lld/ELF/InputFiles.cpp	Tue Jul 31 15:25:03 2018	(r336972)
@@ -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>::createInputSection(co
     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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201807311525.w6VFP3vm058210>