1 //===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_MC_MCASSEMBLER_H
11 #define LLVM_MC_MCASSEMBLER_H
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/ilist.h"
15 #include "llvm/ADT/ilist_node.h"
16 #include "llvm/MC/MCValue.h"
17 #include "llvm/Support/Casting.h"
18 #include "llvm/Support/DataTypes.h"
19 #include <vector> // FIXME: Shouldn't be needed.
27 class MCFragment : public ilist_node<MCFragment> {
28 MCFragment(const MCFragment&); // DO NOT IMPLEMENT
29 void operator=(const MCFragment&); // DO NOT IMPLEMENT
42 /// @name Assembler Backend Data
45 // FIXME: This could all be kept private to the assembler implementation.
47 /// Offset - The offset of this fragment in its section. This is ~0 until
51 /// FileSize - The file size of this section. This is ~0 until initialized.
57 MCFragment(FragmentType _Kind, MCSectionData *SD = 0);
62 virtual ~MCFragment();
64 FragmentType getKind() const { return Kind; }
66 // FIXME: This should be abstract, fix sentinel.
67 virtual uint64_t getMaxFileSize() const {
68 assert(0 && "Invalid getMaxFileSize call!");
72 /// @name Assembler Backend Support
75 // FIXME: This could all be kept private to the assembler implementation.
77 unsigned getFileSize() const {
78 assert(FileSize != ~UINT64_C(0) && "File size not set!");
81 void setFileSize(uint64_t Value) {
82 assert(Value <= getMaxFileSize() && "Invalid file size!");
86 uint64_t getOffset() const {
87 assert(Offset != ~UINT64_C(0) && "File offset not set!");
90 void setOffset(uint64_t Value) { Offset = Value; }
94 static bool classof(const MCFragment *O) { return true; }
97 class MCDataFragment : public MCFragment {
98 SmallString<32> Contents;
101 MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {}
106 uint64_t getMaxFileSize() const {
107 return Contents.size();
110 SmallString<32> &getContents() { return Contents; }
111 const SmallString<32> &getContents() const { return Contents; }
115 static bool classof(const MCFragment *F) {
116 return F->getKind() == MCFragment::FT_Data;
118 static bool classof(const MCDataFragment *) { return true; }
121 class MCAlignFragment : public MCFragment {
122 /// Alignment - The alignment to ensure, in bytes.
125 /// Value - Value to use for filling padding bytes.
128 /// ValueSize - The size of the integer (in bytes) of \arg Value.
131 /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment
132 /// cannot be satisfied in this width then this fragment is ignored.
133 unsigned MaxBytesToEmit;
136 MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize,
137 unsigned _MaxBytesToEmit, MCSectionData *SD = 0)
138 : MCFragment(FT_Align, SD), Alignment(_Alignment),
139 Value(_Value),ValueSize(_ValueSize),
140 MaxBytesToEmit(_MaxBytesToEmit) {}
145 uint64_t getMaxFileSize() const {
146 return std::max(Alignment - 1, MaxBytesToEmit);
149 unsigned getAlignment() const { return Alignment; }
151 int64_t getValue() const { return Value; }
153 unsigned getValueSize() const { return ValueSize; }
155 unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
159 static bool classof(const MCFragment *F) {
160 return F->getKind() == MCFragment::FT_Align;
162 static bool classof(const MCAlignFragment *) { return true; }
165 class MCFillFragment : public MCFragment {
166 /// Value - Value to use for filling bytes.
169 /// ValueSize - The size (in bytes) of \arg Value to use when filling.
172 /// Count - The number of copies of \arg Value to insert.
176 MCFillFragment(MCValue _Value, unsigned _ValueSize, uint64_t _Count,
177 MCSectionData *SD = 0)
178 : MCFragment(FT_Fill, SD),
179 Value(_Value), ValueSize(_ValueSize), Count(_Count) {}
184 uint64_t getMaxFileSize() const {
185 return ValueSize * Count;
188 MCValue getValue() const { return Value; }
190 unsigned getValueSize() const { return ValueSize; }
192 uint64_t getCount() const { return Count; }
196 static bool classof(const MCFragment *F) {
197 return F->getKind() == MCFragment::FT_Fill;
199 static bool classof(const MCFillFragment *) { return true; }
202 class MCOrgFragment : public MCFragment {
203 /// Offset - The offset this fragment should start at.
206 /// Value - Value to use for filling bytes.
210 MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0)
211 : MCFragment(FT_Org, SD),
212 Offset(_Offset), Value(_Value) {}
216 uint64_t getMaxFileSize() const {
217 // FIXME: This doesn't make much sense.
221 MCValue getOffset() const { return Offset; }
223 uint8_t getValue() const { return Value; }
227 static bool classof(const MCFragment *F) {
228 return F->getKind() == MCFragment::FT_Org;
230 static bool classof(const MCOrgFragment *) { return true; }
233 // FIXME: Should this be a separate class, or just merged into MCSection? Since
234 // we anticipate the fast path being through an MCAssembler, the only reason to
235 // keep it out is for API abstraction.
236 class MCSectionData : public ilist_node<MCSectionData> {
237 MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT
238 void operator=(const MCSectionData&); // DO NOT IMPLEMENT
241 typedef iplist<MCFragment> FragmentListType;
243 typedef FragmentListType::const_iterator const_iterator;
244 typedef FragmentListType::iterator iterator;
247 iplist<MCFragment> Fragments;
248 const MCSection &Section;
250 /// Alignment - The maximum alignment seen in this section.
253 /// @name Assembler Backend Data
256 // FIXME: This could all be kept private to the assembler implementation.
258 /// FileSize - The size of this section in the object file. This is ~0 until
265 // Only for use as sentinel.
267 MCSectionData(const MCSection &Section, MCAssembler *A = 0);
269 const MCSection &getSection() const { return Section; }
271 unsigned getAlignment() const { return Alignment; }
272 void setAlignment(unsigned Value) { Alignment = Value; }
274 /// @name Section List Access
277 const FragmentListType &getFragmentList() const { return Fragments; }
278 FragmentListType &getFragmentList() { return Fragments; }
280 iterator begin() { return Fragments.begin(); }
281 const_iterator begin() const { return Fragments.begin(); }
283 iterator end() { return Fragments.end(); }
284 const_iterator end() const { return Fragments.end(); }
286 size_t size() const { return Fragments.size(); }
288 bool empty() const { return Fragments.empty(); }
291 /// @name Assembler Backend Support
294 // FIXME: This could all be kept private to the assembler implementation.
296 unsigned getFileSize() const {
297 assert(FileSize != ~UINT64_C(0) && "File size not set!");
300 void setFileSize(uint64_t Value) { FileSize = Value; }
305 // FIXME: Same concerns as with SectionData.
306 class MCSymbolData : public ilist_node<MCSymbolData> {
310 /// Fragment - The fragment this symbol's value is relative to, if any.
311 MCFragment *Fragment;
313 /// Offset - The offset to apply to the fragment address to form this symbol's
317 /// IsExternal - True if this symbol is visible outside this translation
319 unsigned IsExternal : 1;
321 /// IsPrivateExtern - True if this symbol is private extern.
322 unsigned IsPrivateExtern : 1;
324 /// Flags - The Flags field is used by object file implementations to store
325 /// additional per symbol information which is not easily classified.
329 // Only for use as sentinel.
331 MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset,
337 MCSymbol &getSymbol() const { return Symbol; }
339 MCFragment *getFragment() const { return Fragment; }
340 void setFragment(MCFragment *Value) { Fragment = Value; }
342 uint64_t getOffset() const { return Offset; }
343 void setOffset(uint64_t Value) { Offset = Value; }
346 /// @name Symbol Attributes
349 bool isExternal() const { return IsExternal; }
350 void setExternal(bool Value) { IsExternal = Value; }
352 bool isPrivateExtern() const { return IsPrivateExtern; }
353 void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
355 /// getFlags - Get the (implementation defined) symbol flags.
356 uint32_t getFlags() const { return Flags; }
358 /// setFlags - Set the (implementation defined) symbol flags.
359 void setFlags(uint32_t Value) { Flags = Value; }
364 // FIXME: This really doesn't belong here. See comments below.
365 struct IndirectSymbolData {
367 MCSectionData *SectionData;
372 typedef iplist<MCSectionData> SectionDataListType;
373 typedef iplist<MCSymbolData> SymbolDataListType;
375 typedef SectionDataListType::const_iterator const_iterator;
376 typedef SectionDataListType::iterator iterator;
378 typedef SymbolDataListType::const_iterator const_symbol_iterator;
379 typedef SymbolDataListType::iterator symbol_iterator;
381 typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
384 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
385 void operator=(const MCAssembler&); // DO NOT IMPLEMENT
389 iplist<MCSectionData> Sections;
391 iplist<MCSymbolData> Symbols;
393 std::vector<IndirectSymbolData> IndirectSymbols;
396 /// LayoutSection - Assign offsets and sizes to the fragments in the section
397 /// \arg SD, and update the section size. The section file offset should
398 /// already have been computed.
399 void LayoutSection(MCSectionData &SD);
402 /// Construct a new assembler instance.
404 /// \arg OS - The stream to output to.
406 // FIXME: How are we going to parameterize this? Two obvious options are stay
407 // concrete and require clients to pass in a target like object. The other
408 // option is to make this abstract, and have targets provide concrete
409 // implementations as we do with AsmParser.
410 MCAssembler(raw_ostream &OS);
413 /// Finish - Do final processing and write the object to the output stream.
416 /// @name Section List Access
419 const SectionDataListType &getSectionList() const { return Sections; }
420 SectionDataListType &getSectionList() { return Sections; }
422 iterator begin() { return Sections.begin(); }
423 const_iterator begin() const { return Sections.begin(); }
425 iterator end() { return Sections.end(); }
426 const_iterator end() const { return Sections.end(); }
428 size_t size() const { return Sections.size(); }
431 /// @name Symbol List Access
434 const SymbolDataListType &getSymbolList() const { return Symbols; }
435 SymbolDataListType &getSymbolList() { return Symbols; }
437 symbol_iterator symbol_begin() { return Symbols.begin(); }
438 const_symbol_iterator symbol_begin() const { return Symbols.begin(); }
440 symbol_iterator symbol_end() { return Symbols.end(); }
441 const_symbol_iterator symbol_end() const { return Symbols.end(); }
443 size_t symbol_size() const { return Symbols.size(); }
446 /// @name Indirect Symbol List Access
449 // FIXME: This is a total hack, this should not be here. Once things are
450 // factored so that the streamer has direct access to the .o writer, it can
452 std::vector<IndirectSymbolData> &getIndirectSymbols() {
453 return IndirectSymbols;
456 indirect_symbol_iterator indirect_symbol_begin() {
457 return IndirectSymbols.begin();
460 indirect_symbol_iterator indirect_symbol_end() {
461 return IndirectSymbols.end();
464 size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
469 } // end namespace llvm