MCAssembler.h revision 2ae58f2851188c21517d2d0409db1c37dca84b24
1//===- 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 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 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: 31 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 46 /// Offset - The offset of this fragment in its section. This is ~0 until 47 /// initialized. 48 uint64_t Offset; 49 50 /// FileSize - The file size of this section. This is ~0 until initialized. 51 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. 66 virtual uint64_t getMaxFileSize() const { 67 assert(0 && "Invalid getMaxFileSize call !"); 68 return 0; 69 }; 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 85 uint64_t getOffset() const { 86 assert(Offset != ~UINT64_C(0) && "File offset not set!"); 87 return Offset; 88 } 89 void setOffset(uint64_t Value) { Offset = Value; } 90 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 105 uint64_t getMaxFileSize() const { 106 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 144 uint64_t getMaxFileSize() const { 145 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 183 uint64_t getMaxFileSize() const { 184 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. 206 int8_t Value; 207 208public: 209 MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0) 210 : MCFragment(FT_Org, SD), 211 Offset(_Offset), Value(_Value) {} 212 /// @name Accessors 213 /// @{ 214 215 uint64_t getMaxFileSize() const { 216 // FIXME: This doesn't make much sense. 217 return ~UINT64_C(0); 218 } 219 220 MCValue getOffset() const { return Offset; } 221 222 uint8_t getValue() const { return Value; } 223 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; } 230}; 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 242 typedef FragmentListType::const_iterator const_iterator; 243 typedef FragmentListType::iterator iterator; 244 245private: 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 257 /// FileSize - The size of this section in the object file. This is ~0 until 258 /// initialized. 259 uint64_t FileSize; 260 261 /// @} 262 263public: 264 // Only for use as sentinel. 265 MCSectionData(); 266 MCSectionData(const MCSection &Section, MCAssembler *A = 0); 267 268 const MCSection &getSection() const { return Section; } 269 270 unsigned getAlignment() const { return Alignment; } 271 void setAlignment(unsigned Value) { Alignment = Value; } 272 273 274 /// @name Section List Access 275 /// @{ 276 277 const FragmentListType &getFragmentList() const { return Fragments; } 278 FragmentListType &getFragmentList() { return Fragments; } 279 280 iterator begin() { return Fragments.begin(); } 281 const_iterator begin() const { return Fragments.begin(); } 282 283 iterator end() { return Fragments.end(); } 284 const_iterator end() const { return Fragments.end(); } 285 286 size_t size() const { return Fragments.size(); } 287 288 /// @} 289 /// @name Assembler Backend Support 290 /// @{ 291 // 292 // FIXME: This could all be kept private to the assembler implementation. 293 294 unsigned getFileSize() const { 295 assert(FileSize != ~UINT64_C(0) && "File size not set!"); 296 return FileSize; 297 } 298 void setFileSize(uint64_t Value) { FileSize = Value; } 299 300 /// @} 301}; 302 303class MCAssembler { 304public: 305 typedef iplist<MCSectionData> SectionDataListType; 306 307 typedef SectionDataListType::const_iterator const_iterator; 308 typedef SectionDataListType::iterator iterator; 309 310private: 311 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT 312 void operator=(const MCAssembler&); // DO NOT IMPLEMENT 313 314 raw_ostream &OS; 315 316 iplist<MCSectionData> Sections; 317 318private: 319 /// LayoutSection - Assign offsets and sizes to the fragments in the section 320 /// \arg SD, and update the section size. The section file offset should 321 /// already have been computed. 322 void LayoutSection(MCSectionData &SD); 323 324public: 325 /// Construct a new assembler instance. 326 /// 327 /// \arg OS - The stream to output to. 328 // 329 // FIXME: How are we going to parameterize this? Two obvious options are stay 330 // concrete and require clients to pass in a target like object. The other 331 // option is to make this abstract, and have targets provide concrete 332 // implementations as we do with AsmParser. 333 MCAssembler(raw_ostream &OS); 334 ~MCAssembler(); 335 336 /// Finish - Do final processing and write the object to the output stream. 337 void Finish(); 338 339 /// @name Section List Access 340 /// @{ 341 342 const SectionDataListType &getSectionList() const { return Sections; } 343 SectionDataListType &getSectionList() { return Sections; } 344 345 iterator begin() { return Sections.begin(); } 346 const_iterator begin() const { return Sections.begin(); } 347 348 iterator end() { return Sections.end(); } 349 const_iterator end() const { return Sections.end(); } 350 351 size_t size() const { return Sections.size(); } 352 353 /// @} 354}; 355 356} // end namespace llvm 357 358#endif 359