blob: aae5f08caafa0048c10b4903e2fafe5f8a3c83ec [file] [log] [blame]
Daniel Dunbar7760fbe2009-08-21 09:11:24 +00001//===- MCAssembler.h - Object File Generation -------------------*- 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#ifndef LLVM_MC_MCASSEMBLER_H
11#define LLVM_MC_MCASSEMBLER_H
12
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000013#include "llvm/ADT/SmallString.h"
Daniel Dunbar7760fbe2009-08-21 09:11:24 +000014#include "llvm/ADT/ilist.h"
15#include "llvm/ADT/ilist_node.h"
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000016#include "llvm/MC/MCValue.h"
17#include "llvm/Support/Casting.h"
Benjamin Kramer25550272009-08-21 13:59:49 +000018#include "llvm/Support/DataTypes.h"
Daniel Dunbar7760fbe2009-08-21 09:11:24 +000019
20namespace llvm {
21class raw_ostream;
22class MCAssembler;
23class MCSection;
24class MCSectionData;
25
26class MCFragment : public ilist_node<MCFragment> {
27 MCFragment(const MCFragment&); // DO NOT IMPLEMENT
28 void operator=(const MCFragment&); // DO NOT IMPLEMENT
29
30public:
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000031 enum FragmentType {
32 FT_Data,
33 FT_Align,
34 FT_Fill,
35 FT_Org
36 };
37
38private:
39 FragmentType Kind;
40
41 /// @name Assembler Backend Data
42 /// @{
43 //
44 // FIXME: This could all be kept private to the assembler implementation.
45
Daniel Dunbar1f022e22009-08-22 08:27:54 +000046 /// Offset - The offset of this fragment in its section. This is ~0 until
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000047 /// initialized.
Daniel Dunbar1f022e22009-08-22 08:27:54 +000048 uint64_t Offset;
49
50 /// FileSize - The file size of this section. This is ~0 until initialized.
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000051 uint64_t FileSize;
52
53 /// @}
54
55protected:
56 MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
57
58public:
59 // Only for sentinel.
60 MCFragment();
61 virtual ~MCFragment();
62
63 FragmentType getKind() const { return Kind; }
64
65 // FIXME: This should be abstract, fix sentinel.
Daniel Dunbar3d153ff2009-08-21 23:07:38 +000066 virtual uint64_t getMaxFileSize() const {
Daniel Dunbar197f5632009-08-22 10:13:24 +000067 assert(0 && "Invalid getMaxFileSize call!");
Daniel Dunbar33bf7c22009-08-21 23:11:36 +000068 return 0;
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000069 };
70
71 /// @name Assembler Backend Support
72 /// @{
73 //
74 // FIXME: This could all be kept private to the assembler implementation.
75
76 unsigned getFileSize() const {
77 assert(FileSize != ~UINT64_C(0) && "File size not set!");
78 return FileSize;
79 }
80 void setFileSize(uint64_t Value) {
81 assert(Value <= getMaxFileSize() && "Invalid file size!");
82 FileSize = Value;
83 }
84
Daniel Dunbar1f022e22009-08-22 08:27:54 +000085 uint64_t getOffset() const {
86 assert(Offset != ~UINT64_C(0) && "File offset not set!");
87 return Offset;
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000088 }
Daniel Dunbar1f022e22009-08-22 08:27:54 +000089 void setOffset(uint64_t Value) { Offset = Value; }
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +000090
91 /// @}
92
93 static bool classof(const MCFragment *O) { return true; }
94};
95
96class MCDataFragment : public MCFragment {
97 SmallString<32> Contents;
98
99public:
100 MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {}
101
102 /// @name Accessors
103 /// @{
104
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000105 uint64_t getMaxFileSize() const {
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000106 return Contents.size();
107 }
108
109 SmallString<32> &getContents() { return Contents; }
110 const SmallString<32> &getContents() const { return Contents; }
111
112 /// @}
113
114 static bool classof(const MCFragment *F) {
115 return F->getKind() == MCFragment::FT_Data;
116 }
117 static bool classof(const MCDataFragment *) { return true; }
118};
119
120class MCAlignFragment : public MCFragment {
121 /// Alignment - The alignment to ensure, in bytes.
122 unsigned Alignment;
123
124 /// Value - Value to use for filling padding bytes.
125 int64_t Value;
126
127 /// ValueSize - The size of the integer (in bytes) of \arg Value.
128 unsigned ValueSize;
129
130 /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment
131 /// cannot be satisfied in this width then this fragment is ignored.
132 unsigned MaxBytesToEmit;
133
134public:
135 MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
136 unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
137 : MCFragment(FT_Align, SD), Alignment(_Alignment),
138 Value(_Value),ValueSize(_ValueSize),
139 MaxBytesToEmit(_MaxBytesToEmit) {}
140
141 /// @name Accessors
142 /// @{
143
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000144 uint64_t getMaxFileSize() const {
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000145 return std::max(Alignment - 1, MaxBytesToEmit);
146 }
147
148 unsigned getAlignment() const { return Alignment; }
149
150 int64_t getValue() const { return Value; }
151
152 unsigned getValueSize() const { return ValueSize; }
153
154 unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
155
156 /// @}
157
158 static bool classof(const MCFragment *F) {
159 return F->getKind() == MCFragment::FT_Align;
160 }
161 static bool classof(const MCAlignFragment *) { return true; }
162};
163
164class MCFillFragment : public MCFragment {
165 /// Value - Value to use for filling bytes.
166 MCValue Value;
167
168 /// ValueSize - The size (in bytes) of \arg Value to use when filling.
169 unsigned ValueSize;
170
171 /// Count - The number of copies of \arg Value to insert.
172 uint64_t Count;
173
174public:
175 MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count,
176 MCSectionData *SD = 0)
177 : MCFragment(FT_Fill, SD),
178 Value(_Value), ValueSize(_ValueSize), Count(_Count) {}
179
180 /// @name Accessors
181 /// @{
182
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000183 uint64_t getMaxFileSize() const {
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000184 return ValueSize * Count;
185 }
186
187 MCValue getValue() const { return Value; }
188
189 unsigned getValueSize() const { return ValueSize; }
190
191 uint64_t getCount() const { return Count; }
192
193 /// @}
194
195 static bool classof(const MCFragment *F) {
196 return F->getKind() == MCFragment::FT_Fill;
197 }
198 static bool classof(const MCFillFragment *) { return true; }
199};
200
201class MCOrgFragment : public MCFragment {
202 /// Offset - The offset this fragment should start at.
203 MCValue Offset;
204
205 /// Value - Value to use for filling bytes.
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000206 int8_t Value;
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000207
208public:
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000209 MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0)
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000210 : MCFragment(FT_Org, SD),
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000211 Offset(_Offset), Value(_Value) {}
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000212 /// @name Accessors
213 /// @{
214
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000215 uint64_t getMaxFileSize() const {
216 // FIXME: This doesn't make much sense.
217 return ~UINT64_C(0);
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000218 }
219
220 MCValue getOffset() const { return Offset; }
221
Daniel Dunbar3d153ff2009-08-21 23:07:38 +0000222 uint8_t getValue() const { return Value; }
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000223
224 /// @}
225
226 static bool classof(const MCFragment *F) {
227 return F->getKind() == MCFragment::FT_Org;
228 }
229 static bool classof(const MCOrgFragment *) { return true; }
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000230};
231
232// FIXME: Should this be a separate class, or just merged into MCSection? Since
233// we anticipate the fast path being through an MCAssembler, the only reason to
234// keep it out is for API abstraction.
235class MCSectionData : public ilist_node<MCSectionData> {
236 MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT
237 void operator=(const MCSectionData&); // DO NOT IMPLEMENT
238
239public:
240 typedef iplist<MCFragment> FragmentListType;
241
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000242 typedef FragmentListType::const_iterator const_iterator;
243 typedef FragmentListType::iterator iterator;
244
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000245private:
246 iplist<MCFragment> Fragments;
247 const MCSection &Section;
248
249 /// Alignment - The maximum alignment seen in this section.
250 unsigned Alignment;
251
252 /// @name Assembler Backend Data
253 /// @{
254 //
255 // FIXME: This could all be kept private to the assembler implementation.
256
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000257 /// FileSize - The size of this section in the object file. This is ~0 until
258 /// initialized.
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000259 uint64_t FileSize;
260
261 /// @}
262
263public:
264 // Only for use as sentinel.
265 MCSectionData();
266 MCSectionData(const MCSection &Section, MCAssembler *A = 0);
267
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000268 const MCSection &getSection() const { return Section; }
269
270 unsigned getAlignment() const { return Alignment; }
271 void setAlignment(unsigned Value) { Alignment = Value; }
272
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000273 /// @name Section List Access
274 /// @{
275
276 const FragmentListType &getFragmentList() const { return Fragments; }
277 FragmentListType &getFragmentList() { return Fragments; }
278
279 iterator begin() { return Fragments.begin(); }
280 const_iterator begin() const { return Fragments.begin(); }
281
282 iterator end() { return Fragments.end(); }
283 const_iterator end() const { return Fragments.end(); }
284
285 size_t size() const { return Fragments.size(); }
286
Daniel Dunbar197f5632009-08-22 10:13:24 +0000287 bool empty() const { return Fragments.empty(); }
288
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000289 /// @}
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000290 /// @name Assembler Backend Support
291 /// @{
292 //
293 // FIXME: This could all be kept private to the assembler implementation.
294
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000295 unsigned getFileSize() const {
296 assert(FileSize != ~UINT64_C(0) && "File size not set!");
297 return FileSize;
298 }
299 void setFileSize(uint64_t Value) { FileSize = Value; }
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000300
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000301 /// @}
302};
303
Daniel Dunbar197f5632009-08-22 10:13:24 +0000304// FIXME: Same concerns as with SectionData.
305class MCSymbolData : public ilist_node<MCSymbolData> {
306public:
307 MCSymbol &Symbol;
308
309 /// Fragment - The fragment this symbol's value is relative to, if any.
310 MCFragment *Fragment;
311
312 /// Offset - The offset to apply to the fragment address to form this symbol's
313 /// value.
314 uint64_t Offset;
Daniel Dunbar6fae16d2009-08-22 11:41:10 +0000315
316 /// IsExternal - True if this symbol is visible outside this translation
317 /// unit.
318 unsigned IsExternal : 1;
Daniel Dunbar197f5632009-08-22 10:13:24 +0000319
Daniel Dunbar30b09422009-08-24 08:40:12 +0000320 /// IsPrivateExtern - True if this symbol is private extern.
321 unsigned IsPrivateExtern : 1;
322
323 /// Flags - The Flags field is used by object file implementations to store
324 /// additional per symbol information which is not easily classified.
325 uint32_t Flags;
326
Daniel Dunbar197f5632009-08-22 10:13:24 +0000327public:
328 // Only for use as sentinel.
329 MCSymbolData();
330 MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
331 MCAssembler *A = 0);
332
333 /// @name Accessors
334 /// @{
335
336 MCSymbol &getSymbol() const { return Symbol; }
337
338 MCFragment *getFragment() const { return Fragment; }
339 void setFragment(MCFragment *Value) { Fragment = Value; }
340
341 uint64_t getOffset() const { return Offset; }
342 void setOffset(uint64_t Value) { Offset = Value; }
343
Daniel Dunbar30b09422009-08-24 08:40:12 +0000344 /// @}
345 /// @name Symbol Attributes
346 /// @{
347
348 bool isExternal() const { return IsExternal; }
349 void setExternal(bool Value) { IsExternal = Value; }
350
351 bool isPrivateExtern() const { return IsPrivateExtern; }
352 void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
353
354 /// getFlags - Get the (implementation defined) symbol flags.
355 uint32_t getFlags() const { return Flags; }
Daniel Dunbar6fae16d2009-08-22 11:41:10 +0000356
Daniel Dunbar30b09422009-08-24 08:40:12 +0000357 /// setFlags - Set the (implementation defined) symbol flags.
358 void setFlags(uint32_t Value) { Flags = Value; }
359
Daniel Dunbar197f5632009-08-22 10:13:24 +0000360 /// @}
361};
362
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000363class MCAssembler {
364public:
365 typedef iplist<MCSectionData> SectionDataListType;
Daniel Dunbar197f5632009-08-22 10:13:24 +0000366 typedef iplist<MCSymbolData> SymbolDataListType;
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000367
368 typedef SectionDataListType::const_iterator const_iterator;
369 typedef SectionDataListType::iterator iterator;
370
Daniel Dunbar197f5632009-08-22 10:13:24 +0000371 typedef SymbolDataListType::const_iterator const_symbol_iterator;
372 typedef SymbolDataListType::iterator symbol_iterator;
373
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000374private:
375 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
376 void operator=(const MCAssembler&); // DO NOT IMPLEMENT
377
378 raw_ostream &OS;
379
380 iplist<MCSectionData> Sections;
381
Daniel Dunbar197f5632009-08-22 10:13:24 +0000382 iplist<MCSymbolData> Symbols;
383
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000384private:
385 /// LayoutSection - Assign offsets and sizes to the fragments in the section
386 /// \arg SD, and update the section size. The section file offset should
387 /// already have been computed.
388 void LayoutSection(MCSectionData &SD);
389
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000390public:
391 /// Construct a new assembler instance.
392 ///
393 /// \arg OS - The stream to output to.
394 //
395 // FIXME: How are we going to parameterize this? Two obvious options are stay
396 // concrete and require clients to pass in a target like object. The other
397 // option is to make this abstract, and have targets provide concrete
398 // implementations as we do with AsmParser.
399 MCAssembler(raw_ostream &OS);
400 ~MCAssembler();
401
402 /// Finish - Do final processing and write the object to the output stream.
403 void Finish();
404
405 /// @name Section List Access
406 /// @{
407
408 const SectionDataListType &getSectionList() const { return Sections; }
409 SectionDataListType &getSectionList() { return Sections; }
410
411 iterator begin() { return Sections.begin(); }
412 const_iterator begin() const { return Sections.begin(); }
413
414 iterator end() { return Sections.end(); }
415 const_iterator end() const { return Sections.end(); }
416
417 size_t size() const { return Sections.size(); }
418
419 /// @}
Daniel Dunbar197f5632009-08-22 10:13:24 +0000420 /// @name Symbol List Access
421 /// @{
422
423 const SymbolDataListType &getSymbolList() const { return Symbols; }
424 SymbolDataListType &getSymbolList() { return Symbols; }
425
426 symbol_iterator symbol_begin() { return Symbols.begin(); }
427 const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
428
429 symbol_iterator symbol_end() { return Symbols.end(); }
430 const_symbol_iterator symbol_end() const { return Symbols.end(); }
431
432 size_t symbol_size() const { return Symbols.size(); }
433
434 /// @}
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000435};
436
437} // end namespace llvm
438
439#endif