| OLD | NEW |
| 1 //===- subzero/src/IceAssembler.h - Integrated assembler --------*- C++ -*-===// | 1 //===- subzero/src/IceAssembler.h - Integrated assembler --------*- C++ -*-===// |
| 2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 // | 5 // |
| 6 // Modified by the Subzero authors. | 6 // Modified by the Subzero authors. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // The Subzero Code Generator | 10 // The Subzero Code Generator |
| 11 // | 11 // |
| 12 // This file is distributed under the University of Illinois Open Source | 12 // This file is distributed under the University of Illinois Open Source |
| 13 // License. See LICENSE.TXT for details. | 13 // License. See LICENSE.TXT for details. |
| 14 // | 14 // |
| 15 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 16 /// | 16 /// |
| 17 /// \file | 17 /// \file |
| 18 /// This file declares the Assembler base class. Instructions are assembled | 18 /// This file declares the Assembler base class. Instructions are assembled by |
| 19 /// by architecture-specific assemblers that derive from this base class. | 19 /// architecture-specific assemblers that derive from this base class. This base |
| 20 /// This base class manages buffers and fixups for emitting code, etc. | 20 /// class manages buffers and fixups for emitting code, etc. |
| 21 /// | 21 /// |
| 22 //===----------------------------------------------------------------------===// | 22 //===----------------------------------------------------------------------===// |
| 23 | 23 |
| 24 #ifndef SUBZERO_SRC_ICEASSEMBLER_H | 24 #ifndef SUBZERO_SRC_ICEASSEMBLER_H |
| 25 #define SUBZERO_SRC_ICEASSEMBLER_H | 25 #define SUBZERO_SRC_ICEASSEMBLER_H |
| 26 | 26 |
| 27 #include "IceDefs.h" | 27 #include "IceDefs.h" |
| 28 #include "IceFixups.h" | 28 #include "IceFixups.h" |
| 29 #include "IceUtils.h" | 29 #include "IceUtils.h" |
| 30 | 30 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 48 } | 48 } |
| 49 | 49 |
| 50 /// Returns the position for bound labels (branches that come after this are | 50 /// Returns the position for bound labels (branches that come after this are |
| 51 /// considered backward branches). Cannot be used for unused or linked labels. | 51 /// considered backward branches). Cannot be used for unused or linked labels. |
| 52 intptr_t getPosition() const { | 52 intptr_t getPosition() const { |
| 53 assert(isBound()); | 53 assert(isBound()); |
| 54 return -Position - kWordSize; | 54 return -Position - kWordSize; |
| 55 } | 55 } |
| 56 | 56 |
| 57 /// Returns the position of an earlier branch instruction that was linked to | 57 /// Returns the position of an earlier branch instruction that was linked to |
| 58 /// this label (branches that use this are considered forward branches). The | 58 /// this label (branches that use this are considered forward branches). The |
| 59 /// linked instructions form a linked list, of sorts, using the instruction's | 59 /// linked instructions form a linked list, of sorts, using the instruction's |
| 60 /// displacement field for the location of the next instruction that is also | 60 /// displacement field for the location of the next instruction that is also |
| 61 /// linked to this label. | 61 /// linked to this label. |
| 62 intptr_t getLinkPosition() const { | 62 intptr_t getLinkPosition() const { |
| 63 assert(isLinked()); | 63 assert(isLinked()); |
| 64 return Position - kWordSize; | 64 return Position - kWordSize; |
| 65 } | 65 } |
| 66 | 66 |
| 67 bool isBound() const { return Position < 0; } | 67 bool isBound() const { return Position < 0; } |
| 68 bool isLinked() const { return Position > 0; } | 68 bool isLinked() const { return Position > 0; } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 /// List of pool-allocated fixups relative to the current function. | 193 /// List of pool-allocated fixups relative to the current function. |
| 194 FixupRefList Fixups; | 194 FixupRefList Fixups; |
| 195 | 195 |
| 196 uintptr_t cursor() const { return Cursor; } | 196 uintptr_t cursor() const { return Cursor; } |
| 197 uintptr_t limit() const { return Limit; } | 197 uintptr_t limit() const { return Limit; } |
| 198 intptr_t capacity() const { | 198 intptr_t capacity() const { |
| 199 assert(Limit >= Contents); | 199 assert(Limit >= Contents); |
| 200 return (Limit - Contents) + kMinimumGap; | 200 return (Limit - Contents) + kMinimumGap; |
| 201 } | 201 } |
| 202 | 202 |
| 203 /// Compute the limit based on the data area and the capacity. See | 203 /// Compute the limit based on the data area and the capacity. See description |
| 204 /// description of kMinimumGap for the reasoning behind the value. | 204 /// of kMinimumGap for the reasoning behind the value. |
| 205 static uintptr_t computeLimit(uintptr_t Data, intptr_t Capacity) { | 205 static uintptr_t computeLimit(uintptr_t Data, intptr_t Capacity) { |
| 206 return Data + Capacity - kMinimumGap; | 206 return Data + Capacity - kMinimumGap; |
| 207 } | 207 } |
| 208 | 208 |
| 209 void extendCapacity(); | 209 void extendCapacity(); |
| 210 }; | 210 }; |
| 211 | 211 |
| 212 class Assembler { | 212 class Assembler { |
| 213 Assembler() = delete; | 213 Assembler() = delete; |
| 214 Assembler(const Assembler &) = delete; | 214 Assembler(const Assembler &) = delete; |
| 215 Assembler &operator=(const Assembler &) = delete; | 215 Assembler &operator=(const Assembler &) = delete; |
| 216 | 216 |
| 217 public: | 217 public: |
| 218 enum AssemblerKind { | 218 enum AssemblerKind { |
| 219 Asm_ARM32, | 219 Asm_ARM32, |
| 220 Asm_MIPS32, | 220 Asm_MIPS32, |
| 221 Asm_X8632, | 221 Asm_X8632, |
| 222 Asm_X8664, | 222 Asm_X8664, |
| 223 }; | 223 }; |
| 224 | 224 |
| 225 virtual ~Assembler() = default; | 225 virtual ~Assembler() = default; |
| 226 | 226 |
| 227 /// Allocate a chunk of bytes using the per-Assembler allocator. | 227 /// Allocate a chunk of bytes using the per-Assembler allocator. |
| 228 uintptr_t allocateBytes(size_t bytes) { | 228 uintptr_t allocateBytes(size_t bytes) { |
| 229 // For now, alignment is not related to NaCl bundle alignment, since | 229 // For now, alignment is not related to NaCl bundle alignment, since the |
| 230 // the buffer's GetPosition is relative to the base. So NaCl bundle | 230 // buffer's GetPosition is relative to the base. So NaCl bundle alignment |
| 231 // alignment checks can be relative to that base. Later, the buffer | 231 // checks can be relative to that base. Later, the buffer will be copied |
| 232 // will be copied out to a ".text" section (or an in memory-buffer | 232 // out to a ".text" section (or an in memory-buffer that can be mprotect'ed |
| 233 // that can be mprotect'ed with executable permission), and that | 233 // with executable permission), and that second buffer should be aligned |
| 234 // second buffer should be aligned for NaCl. | 234 // for NaCl. |
| 235 const size_t Alignment = 16; | 235 const size_t Alignment = 16; |
| 236 return reinterpret_cast<uintptr_t>(Allocator.Allocate(bytes, Alignment)); | 236 return reinterpret_cast<uintptr_t>(Allocator.Allocate(bytes, Alignment)); |
| 237 } | 237 } |
| 238 | 238 |
| 239 /// Allocate data of type T using the per-Assembler allocator. | 239 /// Allocate data of type T using the per-Assembler allocator. |
| 240 template <typename T> T *allocate() { return Allocator.Allocate<T>(); } | 240 template <typename T> T *allocate() { return Allocator.Allocate<T>(); } |
| 241 | 241 |
| 242 /// Align the tail end of the function to the required target alignment. | 242 /// Align the tail end of the function to the required target alignment. |
| 243 virtual void alignFunction() = 0; | 243 virtual void alignFunction() = 0; |
| 244 /// Align the tail end of the basic block to the required target alignment. | 244 /// Align the tail end of the basic block to the required target alignment. |
| 245 void alignCfgNode() { | 245 void alignCfgNode() { |
| 246 const SizeT Align = 1 << getBundleAlignLog2Bytes(); | 246 const SizeT Align = 1 << getBundleAlignLog2Bytes(); |
| 247 padWithNop(Utils::OffsetToAlignment(Buffer.getPosition(), Align)); | 247 padWithNop(Utils::OffsetToAlignment(Buffer.getPosition(), Align)); |
| 248 } | 248 } |
| 249 | 249 |
| 250 /// Add nop padding of a particular width to the current bundle. | 250 /// Add nop padding of a particular width to the current bundle. |
| 251 virtual void padWithNop(intptr_t Padding) = 0; | 251 virtual void padWithNop(intptr_t Padding) = 0; |
| 252 | 252 |
| 253 virtual SizeT getBundleAlignLog2Bytes() const = 0; | 253 virtual SizeT getBundleAlignLog2Bytes() const = 0; |
| 254 | 254 |
| 255 virtual const char *getAlignDirective() const = 0; | 255 virtual const char *getAlignDirective() const = 0; |
| 256 virtual llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const = 0; | 256 virtual llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const = 0; |
| 257 | 257 |
| 258 /// Get the label for a CfgNode. | 258 /// Get the label for a CfgNode. |
| 259 virtual Label *getCfgNodeLabel(SizeT NodeNumber) = 0; | 259 virtual Label *getCfgNodeLabel(SizeT NodeNumber) = 0; |
| 260 /// Mark the current text location as the start of a CFG node | 260 /// Mark the current text location as the start of a CFG node (represented by |
| 261 /// (represented by NodeNumber). | 261 /// NodeNumber). |
| 262 virtual void bindCfgNodeLabel(SizeT NodeNumber) = 0; | 262 virtual void bindCfgNodeLabel(SizeT NodeNumber) = 0; |
| 263 | 263 |
| 264 virtual bool fixupIsPCRel(FixupKind Kind) const = 0; | 264 virtual bool fixupIsPCRel(FixupKind Kind) const = 0; |
| 265 | 265 |
| 266 // Return a view of all the bytes of code for the current function. | 266 // Return a view of all the bytes of code for the current function. |
| 267 llvm::StringRef getBufferView() const; | 267 llvm::StringRef getBufferView() const; |
| 268 | 268 |
| 269 const FixupRefList &fixups() const { return Buffer.fixups(); } | 269 const FixupRefList &fixups() const { return Buffer.fixups(); } |
| 270 | 270 |
| 271 AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value) { | 271 AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 286 AssemblerKind getKind() const { return Kind; } | 286 AssemblerKind getKind() const { return Kind; } |
| 287 | 287 |
| 288 protected: | 288 protected: |
| 289 explicit Assembler(AssemblerKind Kind) | 289 explicit Assembler(AssemblerKind Kind) |
| 290 : Kind(Kind), Allocator(), Buffer(*this) {} | 290 : Kind(Kind), Allocator(), Buffer(*this) {} |
| 291 | 291 |
| 292 private: | 292 private: |
| 293 const AssemblerKind Kind; | 293 const AssemblerKind Kind; |
| 294 | 294 |
| 295 ArenaAllocator<32 * 1024> Allocator; | 295 ArenaAllocator<32 * 1024> Allocator; |
| 296 /// FunctionName and IsInternal are transferred from the original Cfg | 296 /// FunctionName and IsInternal are transferred from the original Cfg object, |
| 297 /// object, since the Cfg object may be deleted by the time the | 297 /// since the Cfg object may be deleted by the time the assembler buffer is |
| 298 /// assembler buffer is emitted. | 298 /// emitted. |
| 299 IceString FunctionName = ""; | 299 IceString FunctionName = ""; |
| 300 bool IsInternal = false; | 300 bool IsInternal = false; |
| 301 /// Preliminary indicates whether a preliminary pass is being made | 301 /// Preliminary indicates whether a preliminary pass is being made for |
| 302 /// for calculating bundle padding (Preliminary=true), versus the | 302 /// calculating bundle padding (Preliminary=true), versus the final pass where |
| 303 /// final pass where all changes to label bindings, label links, and | 303 /// all changes to label bindings, label links, and relocation fixups are |
| 304 /// relocation fixups are fully committed (Preliminary=false). | 304 /// fully committed (Preliminary=false). |
| 305 bool Preliminary = false; | 305 bool Preliminary = false; |
| 306 | 306 |
| 307 protected: | 307 protected: |
| 308 // Buffer's constructor uses the Allocator, so it needs to appear after it. | 308 // Buffer's constructor uses the Allocator, so it needs to appear after it. |
| 309 // TODO(jpp): dependencies on construction order are a nice way of shooting | 309 // TODO(jpp): dependencies on construction order are a nice way of shooting |
| 310 // yourself in the foot. Fix this. | 310 // yourself in the foot. Fix this. |
| 311 AssemblerBuffer Buffer; | 311 AssemblerBuffer Buffer; |
| 312 }; | 312 }; |
| 313 | 313 |
| 314 } // end of namespace Ice | 314 } // end of namespace Ice |
| 315 | 315 |
| 316 #endif // SUBZERO_SRC_ICEASSEMBLER_H_ | 316 #endif // SUBZERO_SRC_ICEASSEMBLER_H_ |
| OLD | NEW |