summaryrefslogtreecommitdiff
path: root/devel/llvm60/files/lld/patch-head-r336972.diff
blob: d7497ce5390a71d284c24cbceaedf8caf4ca75a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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.