MCAssembler.h revision d6f761e0eb610936a6b8495360b62696dcd85164
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 /// FileOffset - The offset of this section in the object file. This is ~0 47 /// until initialized. 48 uint64_t FileOffset; 49 50 /// FileSize - The size of this section in the object file. This is ~0 until 51 /// initialized. 52 uint64_t FileSize; 53 54 /// @} 55 56protected: 57 MCFragment(FragmentType _Kind, MCSectionData *SD = 0); 58 59public: 60 // Only for sentinel. 61 MCFragment(); 62 virtual ~MCFragment(); 63 64 FragmentType getKind() const { return Kind; } 65 66 // FIXME: This should be abstract, fix sentinel. 67 virtual uint64_t getMaxFileSize() const { 68 assert(0 && "Invalid getMaxFileSize call !"); 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 getFileOffset() const { 86 assert(FileOffset != ~UINT64_C(0) && "File offset not set!"); 87 return FileOffset; 88 } 89 void setFileOffset(uint64_t Value) { FileOffset = 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 /// FileOffset - The offset of this section in the object file. This is ~0 258 /// until initialized. 259 uint64_t FileOffset; 260 261 /// FileSize - The size of this section in the object file. This is ~0 until 262 /// initialized. 263 uint64_t FileSize; 264 265 /// @} 266 267public: 268 // Only for use as sentinel. 269 MCSectionData(); 270 MCSectionData(const MCSection &Section, MCAssembler *A = 0); 271 272 const MCSection &getSection() const { return Section; } 273 274 unsigned getAlignment() const { return Alignment; } 275 void setAlignment(unsigned Value) { Alignment = Value; } 276 277 278 /// @name Section List Access 279 /// @{ 280 281 const FragmentListType &getFragmentList() const { return Fragments; } 282 FragmentListType &getFragmentList() { return Fragments; } 283 284 iterator begin() { return Fragments.begin(); } 285 const_iterator begin() const { return Fragments.begin(); } 286 287 iterator end() { return Fragments.end(); } 288 const_iterator end() const { return Fragments.end(); } 289 290 size_t size() const { return Fragments.size(); } 291 292 /// @} 293 /// @name Assembler Backend Support 294 /// @{ 295 // 296 // FIXME: This could all be kept private to the assembler implementation. 297 298 unsigned getFileSize() const { 299 assert(FileSize != ~UINT64_C(0) && "File size not set!"); 300 return FileSize; 301 } 302 void setFileSize(uint64_t Value) { FileSize = Value; } 303 304 uint64_t getFileOffset() const { 305 assert(FileOffset != ~UINT64_C(0) && "File offset not set!"); 306 return FileOffset; 307 } 308 void setFileOffset(uint64_t Value) { FileOffset = Value; } 309 310 /// @} 311}; 312 313class MCAssembler { 314public: 315 typedef iplist<MCSectionData> SectionDataListType; 316 317 typedef SectionDataListType::const_iterator const_iterator; 318 typedef SectionDataListType::iterator iterator; 319 320private: 321 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT 322 void operator=(const MCAssembler&); // DO NOT IMPLEMENT 323 324 raw_ostream &OS; 325 326 iplist<MCSectionData> Sections; 327 328private: 329 /// LayoutSection - Assign offsets and sizes to the fragments in the section 330 /// \arg SD, and update the section size. The section file offset should 331 /// already have been computed. 332 void LayoutSection(MCSectionData &SD); 333 334public: 335 /// Construct a new assembler instance. 336 /// 337 /// \arg OS - The stream to output to. 338 // 339 // FIXME: How are we going to parameterize this? Two obvious options are stay 340 // concrete and require clients to pass in a target like object. The other 341 // option is to make this abstract, and have targets provide concrete 342 // implementations as we do with AsmParser. 343 MCAssembler(raw_ostream &OS); 344 ~MCAssembler(); 345 346 /// Finish - Do final processing and write the object to the output stream. 347 void Finish(); 348 349 /// @name Section List Access 350 /// @{ 351 352 const SectionDataListType &getSectionList() const { return Sections; } 353 SectionDataListType &getSectionList() { return Sections; } 354 355 iterator begin() { return Sections.begin(); } 356 const_iterator begin() const { return Sections.begin(); } 357 358 iterator end() { return Sections.end(); } 359 const_iterator end() const { return Sections.end(); } 360 361 size_t size() const { return Sections.size(); } 362 363 /// @} 364}; 365 366} // end namespace llvm 367 368#endif 369