blob: bcd678deaa30d6e97e00fa6b3113d2f07d5a2de5 [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
320public:
321 // Only for use as sentinel.
322 MCSymbolData();
323 MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
324 MCAssembler *A = 0);
325
326 /// @name Accessors
327 /// @{
328
329 MCSymbol &getSymbol() const { return Symbol; }
330
331 MCFragment *getFragment() const { return Fragment; }
332 void setFragment(MCFragment *Value) { Fragment = Value; }
333
334 uint64_t getOffset() const { return Offset; }
335 void setOffset(uint64_t Value) { Offset = Value; }
336
Daniel Dunbar6fae16d2009-08-22 11:41:10 +0000337 /// @}
338 /// @name Symbol Attributes
339 /// @{
340
341 bool isExternal() const { return IsExternal; }
342 void setExternal(bool Value) { IsExternal = Value; }
343
Daniel Dunbar197f5632009-08-22 10:13:24 +0000344 /// @}
345};
346
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000347class MCAssembler {
348public:
349 typedef iplist<MCSectionData> SectionDataListType;
Daniel Dunbar197f5632009-08-22 10:13:24 +0000350 typedef iplist<MCSymbolData> SymbolDataListType;
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000351
352 typedef SectionDataListType::const_iterator const_iterator;
353 typedef SectionDataListType::iterator iterator;
354
Daniel Dunbar197f5632009-08-22 10:13:24 +0000355 typedef SymbolDataListType::const_iterator const_symbol_iterator;
356 typedef SymbolDataListType::iterator symbol_iterator;
357
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000358private:
359 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
360 void operator=(const MCAssembler&); // DO NOT IMPLEMENT
361
362 raw_ostream &OS;
363
364 iplist<MCSectionData> Sections;
365
Daniel Dunbar197f5632009-08-22 10:13:24 +0000366 iplist<MCSymbolData> Symbols;
367
Daniel Dunbar8fcefbe2009-08-21 18:29:01 +0000368private:
369 /// LayoutSection - Assign offsets and sizes to the fragments in the section
370 /// \arg SD, and update the section size. The section file offset should
371 /// already have been computed.
372 void LayoutSection(MCSectionData &SD);
373
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000374public:
375 /// Construct a new assembler instance.
376 ///
377 /// \arg OS - The stream to output to.
378 //
379 // FIXME: How are we going to parameterize this? Two obvious options are stay
380 // concrete and require clients to pass in a target like object. The other
381 // option is to make this abstract, and have targets provide concrete
382 // implementations as we do with AsmParser.
383 MCAssembler(raw_ostream &OS);
384 ~MCAssembler();
385
386 /// Finish - Do final processing and write the object to the output stream.
387 void Finish();
388
389 /// @name Section List Access
390 /// @{
391
392 const SectionDataListType &getSectionList() const { return Sections; }
393 SectionDataListType &getSectionList() { return Sections; }
394
395 iterator begin() { return Sections.begin(); }
396 const_iterator begin() const { return Sections.begin(); }
397
398 iterator end() { return Sections.end(); }
399 const_iterator end() const { return Sections.end(); }
400
401 size_t size() const { return Sections.size(); }
402
403 /// @}
Daniel Dunbar197f5632009-08-22 10:13:24 +0000404 /// @name Symbol List Access
405 /// @{
406
407 const SymbolDataListType &getSymbolList() const { return Symbols; }
408 SymbolDataListType &getSymbolList() { return Symbols; }
409
410 symbol_iterator symbol_begin() { return Symbols.begin(); }
411 const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
412
413 symbol_iterator symbol_end() { return Symbols.end(); }
414 const_symbol_iterator symbol_end() const { return Symbols.end(); }
415
416 size_t symbol_size() const { return Symbols.size(); }
417
418 /// @}
Daniel Dunbar7760fbe2009-08-21 09:11:24 +0000419};
420
421} // end namespace llvm
422
423#endif