1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | #include "llvm/MC/MCELFStreamer.h" |
17 | #include "llvm/ADT/SmallPtrSet.h" |
18 | #include "llvm/ADT/StringExtras.h" |
19 | #include "llvm/ADT/Twine.h" |
20 | #include "llvm/MC/MCAsmBackend.h" |
21 | #include "llvm/MC/MCAsmInfo.h" |
22 | #include "llvm/MC/MCAssembler.h" |
23 | #include "llvm/MC/MCCodeEmitter.h" |
24 | #include "llvm/MC/MCContext.h" |
25 | #include "llvm/MC/MCELF.h" |
26 | #include "llvm/MC/MCELFStreamer.h" |
27 | #include "llvm/MC/MCELFSymbolFlags.h" |
28 | #include "llvm/MC/MCExpr.h" |
29 | #include "llvm/MC/MCInst.h" |
30 | #include "llvm/MC/MCObjectStreamer.h" |
31 | #include "llvm/MC/MCSection.h" |
32 | #include "llvm/MC/MCSectionELF.h" |
33 | #include "llvm/MC/MCStreamer.h" |
34 | #include "llvm/MC/MCSymbol.h" |
35 | #include "llvm/MC/MCValue.h" |
36 | #include "llvm/Support/Debug.h" |
37 | #include "llvm/Support/ELF.h" |
38 | #include "llvm/Support/ErrorHandling.h" |
39 | #include "llvm/Support/FormattedStream.h" |
40 | #include "llvm/Support/raw_ostream.h" |
41 | |
42 | using namespace llvm; |
43 | |
44 | namespace { |
45 | |
46 | class AArch64ELFStreamer; |
47 | |
48 | class AArch64TargetAsmStreamer : public AArch64TargetStreamer { |
49 | formatted_raw_ostream &OS; |
50 | |
51 | void emitInst(uint32_t Inst) override; |
52 | |
53 | public: |
54 | AArch64TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); |
55 | }; |
56 | |
57 | AArch64TargetAsmStreamer::AArch64TargetAsmStreamer(MCStreamer &S, |
58 | formatted_raw_ostream &OS) |
59 | : AArch64TargetStreamer(S), OS(OS) {} |
60 | |
61 | void AArch64TargetAsmStreamer::emitInst(uint32_t Inst) { |
62 | OS << "\t.inst\t0x" << utohexstr(Inst) << "\n"; |
63 | } |
64 | |
65 | class AArch64TargetELFStreamer : public AArch64TargetStreamer { |
66 | private: |
67 | AArch64ELFStreamer &getStreamer(); |
68 | |
69 | void emitInst(uint32_t Inst) override; |
70 | |
71 | public: |
72 | AArch64TargetELFStreamer(MCStreamer &S) : AArch64TargetStreamer(S) {} |
73 | }; |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | class AArch64ELFStreamer : public MCELFStreamer { |
89 | public: |
90 | friend class AArch64TargetELFStreamer; |
91 | |
92 | AArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, |
93 | MCCodeEmitter *Emitter) |
94 | : MCELFStreamer(Context, TAB, OS, Emitter), MappingSymbolCounter(0), |
95 | LastEMS(EMS_None) {} |
96 | |
97 | ~AArch64ELFStreamer() {} |
98 | |
99 | void ChangeSection(const MCSection *Section, |
100 | const MCExpr *Subsection) override { |
101 | |
102 | |
103 | |
104 | LastMappingSymbols[getPreviousSection().first] = LastEMS; |
105 | LastEMS = LastMappingSymbols.lookup(Section); |
106 | |
107 | MCELFStreamer::ChangeSection(Section, Subsection); |
108 | } |
109 | |
110 | |
111 | |
112 | |
113 | void EmitInstruction(const MCInst &Inst, |
114 | const MCSubtargetInfo &STI) override { |
115 | EmitA64MappingSymbol(); |
116 | MCELFStreamer::EmitInstruction(Inst, STI); |
117 | } |
118 | |
119 | void emitInst(uint32_t Inst) { |
120 | char Buffer[4]; |
121 | const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian(); |
122 | |
123 | EmitA64MappingSymbol(); |
| 2 | | Calling 'AArch64ELFStreamer::EmitA64MappingSymbol' | |
|
124 | for (unsigned II = 0; II != 4; ++II) { |
125 | const unsigned I = LittleEndian ? (4 - II - 1) : II; |
126 | Buffer[4 - II - 1] = uint8_t(Inst >> I * CHAR_BIT8); |
127 | } |
128 | MCELFStreamer::EmitBytes(StringRef(Buffer, 4)); |
129 | } |
130 | |
131 | |
132 | |
133 | |
134 | void EmitBytes(StringRef Data) override { |
135 | EmitDataMappingSymbol(); |
136 | MCELFStreamer::EmitBytes(Data); |
137 | } |
138 | |
139 | |
140 | |
141 | |
142 | void EmitValueImpl(const MCExpr *Value, unsigned Size, |
143 | const SMLoc &Loc) override { |
144 | EmitDataMappingSymbol(); |
145 | MCELFStreamer::EmitValueImpl(Value, Size); |
146 | } |
147 | |
148 | private: |
149 | enum ElfMappingSymbol { |
150 | EMS_None, |
151 | EMS_A64, |
152 | EMS_Data |
153 | }; |
154 | |
155 | void EmitDataMappingSymbol() { |
156 | if (LastEMS == EMS_Data) |
157 | return; |
158 | EmitMappingSymbol("$d"); |
159 | LastEMS = EMS_Data; |
160 | } |
161 | |
162 | void EmitA64MappingSymbol() { |
163 | if (LastEMS == EMS_A64) |
| |
164 | return; |
165 | EmitMappingSymbol("$x"); |
| 4 | | Calling 'AArch64ELFStreamer::EmitMappingSymbol' | |
|
166 | LastEMS = EMS_A64; |
167 | } |
168 | |
169 | void EmitMappingSymbol(StringRef Name) { |
170 | MCSymbol *Start = getContext().CreateTempSymbol(); |
171 | EmitLabel(Start); |
172 | |
173 | MCSymbol *Symbol = getContext().GetOrCreateSymbol( |
174 | Name + "." + Twine(MappingSymbolCounter++)); |
175 | |
176 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); |
177 | MCELF::SetType(SD, ELF::STT_NOTYPE); |
178 | MCELF::SetBinding(SD, ELF::STB_LOCAL); |
179 | SD.setExternal(false); |
180 | Symbol->setSection(*getCurrentSection().first); |
| 5 | | Forming reference to null pointer |
|
181 | |
182 | const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); |
183 | Symbol->setVariableValue(Value); |
184 | } |
185 | |
186 | int64_t MappingSymbolCounter; |
187 | |
188 | DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; |
189 | ElfMappingSymbol LastEMS; |
190 | |
191 | |
192 | }; |
193 | } |
194 | |
195 | AArch64ELFStreamer &AArch64TargetELFStreamer::getStreamer() { |
196 | return static_cast<AArch64ELFStreamer &>(Streamer); |
197 | } |
198 | |
199 | void AArch64TargetELFStreamer::emitInst(uint32_t Inst) { |
200 | getStreamer().emitInst(Inst); |
| 1 | Calling 'AArch64ELFStreamer::emitInst' | |
|
201 | } |
202 | |
203 | namespace llvm { |
204 | MCStreamer * |
205 | createAArch64MCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, |
206 | bool isVerboseAsm, bool useDwarfDirectory, |
207 | MCInstPrinter *InstPrint, MCCodeEmitter *CE, |
208 | MCAsmBackend *TAB, bool ShowInst) { |
209 | MCStreamer *S = llvm::createAsmStreamer( |
210 | Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); |
211 | new AArch64TargetAsmStreamer(*S, OS); |
212 | return S; |
213 | } |
214 | |
215 | MCELFStreamer *createAArch64ELFStreamer(MCContext &Context, MCAsmBackend &TAB, |
216 | raw_ostream &OS, MCCodeEmitter *Emitter, |
217 | bool RelaxAll) { |
218 | AArch64ELFStreamer *S = new AArch64ELFStreamer(Context, TAB, OS, Emitter); |
219 | new AArch64TargetELFStreamer(*S); |
220 | if (RelaxAll) |
221 | S->getAssembler().setRelaxAll(true); |
222 | return S; |
223 | } |
224 | } |