/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- lib/MC/AArch64ELFStreamer.cpp - ELF Object Output for AArch64 ------===// |
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 | | // This file assembles .s files and emits AArch64 ELF .o object files. Different |
11 | | // from generic ELF streamer in emitting mapping symbols ($x and $d) to delimit |
12 | | // regions of data and code. |
13 | | // |
14 | | //===----------------------------------------------------------------------===// |
15 | | |
16 | | #include "AArch64TargetStreamer.h" |
17 | | #include "AArch64WinCOFFStreamer.h" |
18 | | #include "llvm/ADT/DenseMap.h" |
19 | | #include "llvm/ADT/StringRef.h" |
20 | | #include "llvm/ADT/Triple.h" |
21 | | #include "llvm/ADT/Twine.h" |
22 | | #include "llvm/BinaryFormat/ELF.h" |
23 | | #include "llvm/MC/MCAsmBackend.h" |
24 | | #include "llvm/MC/MCAssembler.h" |
25 | | #include "llvm/MC/MCCodeEmitter.h" |
26 | | #include "llvm/MC/MCContext.h" |
27 | | #include "llvm/MC/MCELFStreamer.h" |
28 | | #include "llvm/MC/MCExpr.h" |
29 | | #include "llvm/MC/MCInst.h" |
30 | | #include "llvm/MC/MCSection.h" |
31 | | #include "llvm/MC/MCStreamer.h" |
32 | | #include "llvm/MC/MCSubtargetInfo.h" |
33 | | #include "llvm/MC/MCSymbolELF.h" |
34 | | #include "llvm/MC/MCWinCOFFStreamer.h" |
35 | | #include "llvm/Support/Casting.h" |
36 | | #include "llvm/Support/FormattedStream.h" |
37 | | #include "llvm/Support/raw_ostream.h" |
38 | | |
39 | | using namespace llvm; |
40 | | |
41 | | namespace { |
42 | | |
43 | | class AArch64ELFStreamer; |
44 | | |
45 | | class AArch64TargetAsmStreamer : public AArch64TargetStreamer { |
46 | | formatted_raw_ostream &OS; |
47 | | |
48 | | void emitInst(uint32_t Inst) override; |
49 | | |
50 | | public: |
51 | | AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); |
52 | | }; |
53 | | |
54 | | AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S, |
55 | | formatted_raw_ostream &OS) |
56 | 1.22k | : AArch64TargetStreamer(S), OS(OS) {} |
57 | | |
58 | 4 | void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) { |
59 | 4 | OS << "\t.inst\t0x" << Twine::utohexstr(Inst) << "\n"; |
60 | 4 | } |
61 | | |
62 | | class AArch64TargetELFStreamer : public AArch64TargetStreamer { |
63 | | private: |
64 | | AArch64ELFStreamer &getStreamer(); |
65 | | |
66 | | void emitInst(uint32_t Inst) override; |
67 | | |
68 | | public: |
69 | 159 | AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {} |
70 | | }; |
71 | | |
72 | | /// Extend the generic ELFStreamer class so that it can emit mapping symbols at |
73 | | /// the appropriate points in the object files. These symbols are defined in the |
74 | | /// AArch64 ELF ABI: |
75 | | /// infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf |
76 | | /// |
77 | | /// In brief: $x or $d should be emitted at the start of each contiguous region |
78 | | /// of A64 code or data in a section. In practice, this emission does not rely |
79 | | /// on explicit assembler directives but on inherent properties of the |
80 | | /// directives doing the emission (e.g. ".byte" is data, "add x0, x0, x0" an |
81 | | /// instruction). |
82 | | /// |
83 | | /// As a result this system is orthogonal to the DataRegion infrastructure used |
84 | | /// by MachO. Beware! |
85 | | class AArch64ELFStreamer : public MCELFStreamer { |
86 | | public: |
87 | | friend class AArch64TargetELFStreamer; |
88 | | |
89 | | AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, |
90 | | raw_pwrite_stream &OS, MCCodeEmitter *Emitter) |
91 | | : MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0), |
92 | 159 | LastEMS(EMS_None) {} |
93 | | |
94 | 368 | void ChangeSection(MCSection *Section, const MCExpr *Subsection) override { |
95 | 368 | // We have to keep track of the mapping symbol state of any sections we |
96 | 368 | // use. Each one should start off as EMS_None, which is provided as the |
97 | 368 | // default constructor by DenseMap::lookup. |
98 | 368 | LastMappingSymbols[getPreviousSection().first] = LastEMS; |
99 | 368 | LastEMS = LastMappingSymbols.lookup(Section); |
100 | 368 | |
101 | 368 | MCELFStreamer::ChangeSection(Section, Subsection); |
102 | 368 | } |
103 | | |
104 | | /// This function is the one used to emit instruction data into the ELF |
105 | | /// streamer. We override it to add the appropriate mapping symbol if |
106 | | /// necessary. |
107 | | void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, |
108 | 1.00k | bool) override { |
109 | 1.00k | EmitA64MappingSymbol(); |
110 | 1.00k | MCELFStreamer::EmitInstruction(Inst, STI); |
111 | 1.00k | } |
112 | | |
113 | | /// Emit a 32-bit value as an instruction. This is only used for the .inst |
114 | | /// directive, EmitInstruction should be used in other cases. |
115 | 2 | void emitInst(uint32_t Inst) { |
116 | 2 | char Buffer[4]; |
117 | 2 | |
118 | 2 | // We can't just use EmitIntValue here, as that will emit a data mapping |
119 | 2 | // symbol, and swap the endianness on big-endian systems (instructions are |
120 | 2 | // always little-endian). |
121 | 10 | for (unsigned I = 0; I < 410 ; ++I8 ) { |
122 | 8 | Buffer[I] = uint8_t(Inst); |
123 | 8 | Inst >>= 8; |
124 | 8 | } |
125 | 2 | |
126 | 2 | EmitA64MappingSymbol(); |
127 | 2 | MCELFStreamer::EmitBytes(StringRef(Buffer, 4)); |
128 | 2 | } |
129 | | |
130 | | /// This is one of the functions used to emit data into an ELF section, so the |
131 | | /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) |
132 | | /// if necessary. |
133 | 1.84k | void EmitBytes(StringRef Data) override { |
134 | 1.84k | EmitDataMappingSymbol(); |
135 | 1.84k | MCELFStreamer::EmitBytes(Data); |
136 | 1.84k | } |
137 | | |
138 | | /// This is one of the functions used to emit data into an ELF section, so the |
139 | | /// AArch64 streamer overrides it to add the appropriate mapping symbol ($d) |
140 | | /// if necessary. |
141 | 392 | void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { |
142 | 392 | EmitDataMappingSymbol(); |
143 | 392 | MCELFStreamer::EmitValueImpl(Value, Size, Loc); |
144 | 392 | } |
145 | | |
146 | | private: |
147 | | enum ElfMappingSymbol { |
148 | | EMS_None, |
149 | | EMS_A64, |
150 | | EMS_Data |
151 | | }; |
152 | | |
153 | 2.23k | void EmitDataMappingSymbol() { |
154 | 2.23k | if (LastEMS == EMS_Data) |
155 | 2.09k | return; |
156 | 140 | EmitMappingSymbol("$d"); |
157 | 140 | LastEMS = EMS_Data; |
158 | 140 | } |
159 | | |
160 | 1.00k | void EmitA64MappingSymbol() { |
161 | 1.00k | if (LastEMS == EMS_A64) |
162 | 879 | return; |
163 | 130 | EmitMappingSymbol("$x"); |
164 | 130 | LastEMS = EMS_A64; |
165 | 130 | } |
166 | | |
167 | 270 | void EmitMappingSymbol(StringRef Name) { |
168 | 270 | auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol( |
169 | 270 | Name + "." + Twine(MappingSymbolCounter++))); |
170 | 270 | EmitLabel(Symbol); |
171 | 270 | Symbol->setType(ELF::STT_NOTYPE); |
172 | 270 | Symbol->setBinding(ELF::STB_LOCAL); |
173 | 270 | Symbol->setExternal(false); |
174 | 270 | } |
175 | | |
176 | | int64_t MappingSymbolCounter; |
177 | | |
178 | | DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; |
179 | | ElfMappingSymbol LastEMS; |
180 | | }; |
181 | | |
182 | | } // end anonymous namespace |
183 | | |
184 | 2 | AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() { |
185 | 2 | return static_cast<AArch64ELFStreamer &>(Streamer); |
186 | 2 | } |
187 | | |
188 | 2 | void AArch64TargetELFStreamer::emitInst(uint32_t Inst) { |
189 | 2 | getStreamer().emitInst(Inst); |
190 | 2 | } |
191 | | |
192 | | namespace llvm { |
193 | | |
194 | | MCTargetStreamer *createAArch64AsmTargetStreamer(MCStreamer &S, |
195 | | formatted_raw_ostream &OS, |
196 | | MCInstPrinter *InstPrint, |
197 | 1.22k | bool isVerboseAsm) { |
198 | 1.22k | return new AArch64TargetAsmStreamer(S, OS); |
199 | 1.22k | } |
200 | | |
201 | | MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, |
202 | | raw_pwrite_stream &OS, |
203 | 159 | MCCodeEmitter *Emitter, bool RelaxAll) { |
204 | 159 | AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter); |
205 | 159 | if (RelaxAll) |
206 | 0 | S->getAssembler().setRelaxAll(true); |
207 | 159 | return S; |
208 | 159 | } |
209 | | |
210 | | MCTargetStreamer * |
211 | 13.1k | createAArch64ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { |
212 | 13.1k | const Triple &TT = STI.getTargetTriple(); |
213 | 13.1k | if (TT.isOSBinFormatELF()) |
214 | 159 | return new AArch64TargetELFStreamer(S); |
215 | 12.9k | if (12.9k TT.isOSBinFormatCOFF()12.9k ) |
216 | 5 | return new AArch64TargetWinCOFFStreamer(S); |
217 | 12.9k | return nullptr; |
218 | 12.9k | } |
219 | | |
220 | | } // end namespace llvm |