Skip to content

Commit 53d3251

Browse files
committed
MachO: Add linker-optimisation hint framework to MC.
Another part of the ARM64 backend (so tests will be following soon). This is currently used by the linker to relax adrp/ldr pairs into nops where possible, though could well be more broadly applicable. llvm-svn: 205084
1 parent 5627670 commit 53d3251

10 files changed

+325
-3
lines changed

llvm/include/llvm/MC/MCAssembler.h

+18
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/MC/MCDirectives.h"
1919
#include "llvm/MC/MCFixup.h"
2020
#include "llvm/MC/MCInst.h"
21+
#include "llvm/MC/MCLinkerOptimizationHint.h"
2122
#include "llvm/MC/MCSubtargetInfo.h"
2223
#include "llvm/Support/Casting.h"
2324
#include "llvm/Support/DataTypes.h"
@@ -932,6 +933,10 @@ class MCAssembler {
932933
// which flags to be set.
933934
unsigned ELFHeaderEFlags;
934935

936+
/// Used to communicate Linker Optimization Hint information between
937+
/// the Streamer and the .o writer
938+
MCLOHContainer LOHContainer;
939+
935940
VersionMinInfoType VersionMinInfo;
936941
private:
937942
/// Evaluate a fixup to a relocatable expression and the value which should be
@@ -1174,6 +1179,19 @@ class MCAssembler {
11741179

11751180
size_t data_region_size() const { return DataRegions.size(); }
11761181

1182+
/// @}
1183+
/// @name Data Region List Access
1184+
/// @{
1185+
1186+
// FIXME: This is a total hack, this should not be here. Once things are
1187+
// factored so that the streamer has direct access to the .o writer, it can
1188+
// disappear.
1189+
MCLOHContainer & getLOHContainer() {
1190+
return LOHContainer;
1191+
}
1192+
const MCLOHContainer & getLOHContainer() const {
1193+
return const_cast<MCAssembler *>(this)->getLOHContainer();
1194+
}
11771195
/// @}
11781196
/// @name Backend Data Access
11791197
/// @{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
//===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===//
2+
//
3+
//
4+
// The LLVM Compiler Infrastructure
5+
//
6+
// This file is distributed under the University of Illinois Open Source
7+
// License. See LICENSE.TXT for details.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
//
11+
// This file declares some helpers classes to handle Linker Optimization Hint
12+
// (LOH).
13+
//
14+
// FIXME: LOH interface supports only MachO format at the moment.
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
18+
#define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
19+
20+
#include "llvm/ADT/SmallVector.h"
21+
#include "llvm/ADT/StringSwitch.h"
22+
#include "llvm/ADT/StringRef.h"
23+
#include "llvm/MC/MCMachObjectWriter.h"
24+
#include "llvm/Support/raw_ostream.h"
25+
26+
namespace llvm {
27+
28+
// Forward declarations.
29+
class MCAsmLayout;
30+
class MCSymbol;
31+
32+
/// Linker Optimization Hint Type.
33+
enum MCLOHType {
34+
MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.
35+
MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF.
36+
MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.
37+
MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.
38+
MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.
39+
MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.
40+
MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF.
41+
MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.
42+
};
43+
44+
static inline StringRef MCLOHDirectiveName() {
45+
return StringRef(".loh");
46+
}
47+
48+
static inline bool isValidMCLOHType(MCLOHType Kind) {
49+
return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot;
50+
}
51+
52+
static inline int MCLOHNameToId(StringRef Name) {
53+
#define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name)
54+
return StringSwitch<int>(Name)
55+
MCLOHCaseNameToId(AdrpAdrp)
56+
MCLOHCaseNameToId(AdrpLdr)
57+
MCLOHCaseNameToId(AdrpAddLdr)
58+
MCLOHCaseNameToId(AdrpLdrGotLdr)
59+
MCLOHCaseNameToId(AdrpAddStr)
60+
MCLOHCaseNameToId(AdrpLdrGotStr)
61+
MCLOHCaseNameToId(AdrpAdd)
62+
MCLOHCaseNameToId(AdrpLdrGot)
63+
.Default(-1);
64+
}
65+
66+
static inline StringRef MCLOHIdToName(MCLOHType Kind) {
67+
#define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name);
68+
switch (Kind) {
69+
MCLOHCaseIdToName(AdrpAdrp);
70+
MCLOHCaseIdToName(AdrpLdr);
71+
MCLOHCaseIdToName(AdrpAddLdr);
72+
MCLOHCaseIdToName(AdrpLdrGotLdr);
73+
MCLOHCaseIdToName(AdrpAddStr);
74+
MCLOHCaseIdToName(AdrpLdrGotStr);
75+
MCLOHCaseIdToName(AdrpAdd);
76+
MCLOHCaseIdToName(AdrpLdrGot);
77+
}
78+
return StringRef();
79+
}
80+
81+
static inline int MCLOHIdToNbArgs(MCLOHType Kind) {
82+
switch (Kind) {
83+
// LOH with two arguments
84+
case MCLOH_AdrpAdrp:
85+
case MCLOH_AdrpLdr:
86+
case MCLOH_AdrpAdd:
87+
case MCLOH_AdrpLdrGot:
88+
return 2;
89+
// LOH with three arguments
90+
case MCLOH_AdrpAddLdr:
91+
case MCLOH_AdrpLdrGotLdr:
92+
case MCLOH_AdrpAddStr:
93+
case MCLOH_AdrpLdrGotStr:
94+
return 3;
95+
}
96+
return -1;
97+
}
98+
99+
/// Store Linker Optimization Hint information (LOH).
100+
template<typename T>
101+
class LOHDirective {
102+
private:
103+
MCLOHType Kind;
104+
105+
/// Arguments of this directive. Order matters.
106+
SmallVector<T *, 3> Args;
107+
108+
/// Emit this directive in @p OutStream using the information available
109+
/// in the given @p ObjWriter and @p Layout to get the address of the
110+
/// arguments within the object file.
111+
/// This function is currently specialized for T = MCSymbol.
112+
void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
113+
const MCAsmLayout &Layout) const { }
114+
115+
public:
116+
typedef SmallVectorImpl<T *> LOHArgs;
117+
118+
LOHDirective(MCLOHType Kind, const LOHArgs &Args)
119+
: Kind(Kind), Args(Args.begin(), Args.end()) {};
120+
121+
MCLOHType getKind() const { return Kind; }
122+
123+
const LOHArgs & getArgs() const { return Args; }
124+
125+
/// Emit this directive as:
126+
/// <kind, numArgs, addr1, ..., addrN>
127+
void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
128+
raw_ostream &OutStream = ObjWriter.getStream();
129+
Emit_impl(OutStream, ObjWriter, Layout);
130+
}
131+
132+
/// Get the size in bytes of this directive if emitted in @p ObjWriter with
133+
/// the given @p Layout.
134+
uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
135+
const MCAsmLayout &Layout) const {
136+
std::string Buffer;
137+
raw_string_ostream OutStream(Buffer);
138+
Emit_impl(OutStream, ObjWriter, Layout);
139+
return OutStream.tell();
140+
}
141+
};
142+
143+
template<typename T>
144+
class LOHContainer {
145+
public:
146+
typedef SmallVectorImpl<LOHDirective<T> > LOHDirectives;
147+
148+
private:
149+
/// Keep track of the emit size of all the LOHs.
150+
mutable uint64_t EmitSize;
151+
152+
/// Keep track of all LOH directives.
153+
SmallVector<LOHDirective<T>, 32> Directives;
154+
155+
/// Accessor to the directives.
156+
LOHDirectives &getDirectives() { return Directives; }
157+
158+
public:
159+
LOHContainer() : EmitSize(0) {};
160+
161+
/// Const accessor to the directives.
162+
const LOHDirectives &getDirectives() const {
163+
return const_cast<LOHContainer *>(this)->getDirectives();
164+
}
165+
166+
/// Add the directive of the given kind @p Kind with the given arguments
167+
/// @p Args to the container.
168+
void addDirective(MCLOHType Kind,
169+
const typename LOHDirective<T>::LOHArgs &Args) {
170+
assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
171+
getDirectives().push_back(LOHDirective<T>(Kind, Args));
172+
}
173+
174+
/// Get the size of the directives if emitted.
175+
uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
176+
const MCAsmLayout &Layout) const {
177+
if (!EmitSize) {
178+
for (typename LOHDirectives::const_iterator It = getDirectives().begin(),
179+
EndIt = getDirectives().end(); It != EndIt; ++It)
180+
EmitSize += It->getEmitSize(ObjWriter, Layout);
181+
}
182+
return EmitSize;
183+
}
184+
185+
/// Emit all Linker Optimization Hint in one big table.
186+
/// Each line of the table is emitted by LOHDirective::Emit.
187+
void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
188+
for (typename LOHDirectives::const_iterator It = getDirectives().begin(),
189+
EndIt = getDirectives().end(); It != EndIt; ++It)
190+
It->Emit(ObjWriter, Layout);
191+
}
192+
193+
void reset() {
194+
getDirectives().clear();
195+
EmitSize = 0;
196+
}
197+
};
198+
199+
// Add types for specialized template using MCSymbol.
200+
typedef LOHDirective<MCSymbol> MCLOHDirective;
201+
typedef LOHDirective<MCSymbol>::LOHArgs MCLOHArgs;
202+
203+
typedef LOHContainer<MCLOHDirective>::LOHDirectives MCLOHDirectives;
204+
205+
typedef LOHContainer<MCSymbol> MCLOHContainer;
206+
207+
// Declare the specialization for MCSymbol.
208+
template<>
209+
void MCLOHDirective::Emit_impl(raw_ostream &OutStream,
210+
const MachObjectWriter &ObjWriter,
211+
const MCAsmLayout &Layout) const;
212+
} // end namespace llvm
213+
214+
#endif

llvm/include/llvm/MC/MCStreamer.h

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/MC/MCAssembler.h"
2020
#include "llvm/MC/MCDirectives.h"
2121
#include "llvm/MC/MCDwarf.h"
22+
#include "llvm/MC/MCLinkerOptimizationHint.h"
2223
#include "llvm/MC/MCWin64EH.h"
2324
#include "llvm/Support/DataTypes.h"
2425
#include <string>
@@ -466,6 +467,10 @@ class MCStreamer {
466467
///
467468
virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0;
468469

470+
/// \brief Emit a Linker Optimization Hint (LOH) directive.
471+
/// \param Args - Arguments of the LOH.
472+
virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {}
473+
469474
/// EmitCommonSymbol - Emit a common symbol.
470475
///
471476
/// @param Symbol - The common symbol to emit.

llvm/include/llvm/Support/MachO.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ namespace llvm {
128128
LC_SOURCE_VERSION = 0x0000002Au,
129129
LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu,
130130
// 0x0000002Cu,
131-
LC_LINKER_OPTIONS = 0x0000002Du
131+
LC_LINKER_OPTIONS = 0x0000002Du,
132+
LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu
132133
};
133134

134135
enum : uint32_t {

llvm/lib/MC/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ add_llvm_library(LLVMMC
2424
MCInstPrinter.cpp
2525
MCInstrAnalysis.cpp
2626
MCLabel.cpp
27+
MCLinkerOptimizationHint.cpp
2728
MCMachOStreamer.cpp
2829
MCMachObjectTargetWriter.cpp
2930
MCModule.cpp

llvm/lib/MC/MCAsmStreamer.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class MCAsmStreamer : public MCStreamer {
126126
void ChangeSection(const MCSection *Section,
127127
const MCExpr *Subsection) override;
128128

129+
void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
129130
void EmitLabel(MCSymbol *Symbol) override;
130131
void EmitDebugLabel(MCSymbol *Symbol) override;
131132

@@ -342,6 +343,27 @@ void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
342343
EmitEOL();
343344
}
344345

346+
void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
347+
StringRef str = MCLOHIdToName(Kind);
348+
349+
#ifndef NDEBUG
350+
int NbArgs = MCLOHIdToNbArgs(Kind);
351+
assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
352+
assert(str != "" && "Invalid LOH name");
353+
#endif
354+
355+
OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
356+
bool IsFirst = true;
357+
for (MCLOHArgs::const_iterator It = Args.begin(), EndIt = Args.end();
358+
It != EndIt; ++It) {
359+
if (!IsFirst)
360+
OS << ", ";
361+
IsFirst = false;
362+
OS << **It;
363+
}
364+
EmitEOL();
365+
}
366+
345367
void MCAsmStreamer::EmitDebugLabel(MCSymbol *Symbol) {
346368
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
347369
MCStreamer::EmitDebugLabel(Symbol);

llvm/lib/MC/MCAssembler.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ void MCAssembler::reset() {
355355
getBackend().reset();
356356
getEmitter().reset();
357357
getWriter().reset();
358+
getLOHContainer().reset();
358359
}
359360

360361
bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===-- llvm/MC/MCLinkerOptimizationHint.cpp ----- LOH handling -*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "llvm/MC/MCLinkerOptimizationHint.h"
11+
#include "llvm/MC/MCAsmLayout.h"
12+
#include "llvm/Support/LEB128.h"
13+
#include "llvm/MC/MCStreamer.h"
14+
15+
using namespace llvm;
16+
17+
namespace llvm {
18+
template<>
19+
void MCLOHDirective::Emit_impl(raw_ostream &OutStream,
20+
const MachObjectWriter &ObjWriter,
21+
const MCAsmLayout &Layout) const {
22+
const MCAssembler &Asm = Layout.getAssembler();
23+
encodeULEB128(Kind, OutStream);
24+
encodeULEB128(Args.size(), OutStream);
25+
for (LOHArgs::const_iterator It = Args.begin(), EndIt = Args.end();
26+
It != EndIt; ++It)
27+
encodeULEB128(ObjWriter.getSymbolAddress(&Asm.getSymbolData(**It), Layout),
28+
OutStream);
29+
}
30+
} // end namespace llvm

llvm/lib/MC/MCMachOStreamer.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/MC/MCDwarf.h"
1818
#include "llvm/MC/MCExpr.h"
1919
#include "llvm/MC/MCInst.h"
20+
#include "llvm/MC/MCLinkerOptimizationHint.h"
2021
#include "llvm/MC/MCMachOSymbolFlags.h"
2122
#include "llvm/MC/MCObjectFileInfo.h"
2223
#include "llvm/MC/MCObjectStreamer.h"
@@ -104,6 +105,10 @@ class MCMachOStreamer : public MCObjectStreamer {
104105
llvm_unreachable("macho doesn't support this directive");
105106
}
106107

108+
void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {
109+
getAssembler().getLOHContainer().addDirective(Kind, Args);
110+
}
111+
107112
void FinishImpl() override;
108113
};
109114

0 commit comments

Comments
 (0)