1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceAssembler.h - Integrated assembler --------*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 3*03ce13f7SAndroid Build Coastguard Worker // for details. All rights reserved. Use of this source code is governed by a 4*03ce13f7SAndroid Build Coastguard Worker // BSD-style license that can be found in the LICENSE file. 5*03ce13f7SAndroid Build Coastguard Worker // 6*03ce13f7SAndroid Build Coastguard Worker // Modified by the Subzero authors. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker // 10*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 11*03ce13f7SAndroid Build Coastguard Worker // 12*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 13*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 14*03ce13f7SAndroid Build Coastguard Worker // 15*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 16*03ce13f7SAndroid Build Coastguard Worker /// 17*03ce13f7SAndroid Build Coastguard Worker /// \file 18*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the Assembler base class. 19*03ce13f7SAndroid Build Coastguard Worker /// 20*03ce13f7SAndroid Build Coastguard Worker /// Instructions are assembled by architecture-specific assemblers that derive 21*03ce13f7SAndroid Build Coastguard Worker /// from this base class. This base class manages buffers and fixups for 22*03ce13f7SAndroid Build Coastguard Worker /// emitting code, etc. 23*03ce13f7SAndroid Build Coastguard Worker /// 24*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 25*03ce13f7SAndroid Build Coastguard Worker 26*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEASSEMBLER_H 27*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEASSEMBLER_H 28*03ce13f7SAndroid Build Coastguard Worker 29*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 30*03ce13f7SAndroid Build Coastguard Worker #include "IceFixups.h" 31*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h" 32*03ce13f7SAndroid Build Coastguard Worker #include "IceUtils.h" 33*03ce13f7SAndroid Build Coastguard Worker 34*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Allocator.h" 35*03ce13f7SAndroid Build Coastguard Worker 36*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 37*03ce13f7SAndroid Build Coastguard Worker 38*03ce13f7SAndroid Build Coastguard Worker class Assembler; 39*03ce13f7SAndroid Build Coastguard Worker 40*03ce13f7SAndroid Build Coastguard Worker /// A Label can be in one of three states: 41*03ce13f7SAndroid Build Coastguard Worker /// - Unused. 42*03ce13f7SAndroid Build Coastguard Worker /// - Linked, unplaced and tracking the position of branches to the label. 43*03ce13f7SAndroid Build Coastguard Worker /// - Bound, placed and tracking its position. 44*03ce13f7SAndroid Build Coastguard Worker class Label { 45*03ce13f7SAndroid Build Coastguard Worker Label(const Label &) = delete; 46*03ce13f7SAndroid Build Coastguard Worker Label &operator=(const Label &) = delete; 47*03ce13f7SAndroid Build Coastguard Worker 48*03ce13f7SAndroid Build Coastguard Worker public: 49*03ce13f7SAndroid Build Coastguard Worker Label() = default; 50*03ce13f7SAndroid Build Coastguard Worker virtual ~Label() = default; 51*03ce13f7SAndroid Build Coastguard Worker finalCheck()52*03ce13f7SAndroid Build Coastguard Worker virtual void finalCheck() const { 53*03ce13f7SAndroid Build Coastguard Worker // Assert if label is being destroyed with unresolved branches pending. 54*03ce13f7SAndroid Build Coastguard Worker assert(!isLinked()); 55*03ce13f7SAndroid Build Coastguard Worker } 56*03ce13f7SAndroid Build Coastguard Worker 57*03ce13f7SAndroid Build Coastguard Worker /// Returns the encoded position stored in the label. getEncodedPosition()58*03ce13f7SAndroid Build Coastguard Worker intptr_t getEncodedPosition() const { return Position; } 59*03ce13f7SAndroid Build Coastguard Worker 60*03ce13f7SAndroid Build Coastguard Worker /// Returns the position for bound labels (branches that come after this are 61*03ce13f7SAndroid Build Coastguard Worker /// considered backward branches). Cannot be used for unused or linked labels. getPosition()62*03ce13f7SAndroid Build Coastguard Worker intptr_t getPosition() const { 63*03ce13f7SAndroid Build Coastguard Worker assert(isBound()); 64*03ce13f7SAndroid Build Coastguard Worker return -Position - kWordSize; 65*03ce13f7SAndroid Build Coastguard Worker } 66*03ce13f7SAndroid Build Coastguard Worker 67*03ce13f7SAndroid Build Coastguard Worker /// Returns the position of an earlier branch instruction that was linked to 68*03ce13f7SAndroid Build Coastguard Worker /// this label (branches that use this are considered forward branches). The 69*03ce13f7SAndroid Build Coastguard Worker /// linked instructions form a linked list, of sorts, using the instruction's 70*03ce13f7SAndroid Build Coastguard Worker /// displacement field for the location of the next instruction that is also 71*03ce13f7SAndroid Build Coastguard Worker /// linked to this label. getLinkPosition()72*03ce13f7SAndroid Build Coastguard Worker intptr_t getLinkPosition() const { 73*03ce13f7SAndroid Build Coastguard Worker assert(isLinked()); 74*03ce13f7SAndroid Build Coastguard Worker return Position - kWordSize; 75*03ce13f7SAndroid Build Coastguard Worker } 76*03ce13f7SAndroid Build Coastguard Worker setPosition(intptr_t NewValue)77*03ce13f7SAndroid Build Coastguard Worker void setPosition(intptr_t NewValue) { Position = NewValue; } 78*03ce13f7SAndroid Build Coastguard Worker isBound()79*03ce13f7SAndroid Build Coastguard Worker bool isBound() const { return Position < 0; } isLinked()80*03ce13f7SAndroid Build Coastguard Worker bool isLinked() const { return Position > 0; } 81*03ce13f7SAndroid Build Coastguard Worker isUnused()82*03ce13f7SAndroid Build Coastguard Worker virtual bool isUnused() const { return Position == 0; } 83*03ce13f7SAndroid Build Coastguard Worker bindTo(intptr_t position)84*03ce13f7SAndroid Build Coastguard Worker void bindTo(intptr_t position) { 85*03ce13f7SAndroid Build Coastguard Worker assert(!isBound()); 86*03ce13f7SAndroid Build Coastguard Worker Position = -position - kWordSize; 87*03ce13f7SAndroid Build Coastguard Worker assert(isBound()); 88*03ce13f7SAndroid Build Coastguard Worker } 89*03ce13f7SAndroid Build Coastguard Worker 90*03ce13f7SAndroid Build Coastguard Worker void linkTo(const Assembler &Asm, intptr_t position); 91*03ce13f7SAndroid Build Coastguard Worker 92*03ce13f7SAndroid Build Coastguard Worker protected: 93*03ce13f7SAndroid Build Coastguard Worker intptr_t Position = 0; 94*03ce13f7SAndroid Build Coastguard Worker 95*03ce13f7SAndroid Build Coastguard Worker // TODO(jvoung): why are labels offset by this? 96*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t kWordSize = sizeof(uint32_t); 97*03ce13f7SAndroid Build Coastguard Worker }; 98*03ce13f7SAndroid Build Coastguard Worker 99*03ce13f7SAndroid Build Coastguard Worker /// Assembler buffers are used to emit binary code. They grow on demand. 100*03ce13f7SAndroid Build Coastguard Worker class AssemblerBuffer { 101*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer(const AssemblerBuffer &) = delete; 102*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer &operator=(const AssemblerBuffer &) = delete; 103*03ce13f7SAndroid Build Coastguard Worker 104*03ce13f7SAndroid Build Coastguard Worker public: 105*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer(Assembler &); 106*03ce13f7SAndroid Build Coastguard Worker ~AssemblerBuffer(); 107*03ce13f7SAndroid Build Coastguard Worker 108*03ce13f7SAndroid Build Coastguard Worker /// \name Basic support for emitting, loading, and storing. 109*03ce13f7SAndroid Build Coastguard Worker /// @{ 110*03ce13f7SAndroid Build Coastguard Worker // These use memcpy instead of assignment to avoid undefined behaviour of 111*03ce13f7SAndroid Build Coastguard Worker // assigning to unaligned addresses. Since the size of the copy is known the 112*03ce13f7SAndroid Build Coastguard Worker // compiler can inline the memcpy with simple moves. emit(T Value)113*03ce13f7SAndroid Build Coastguard Worker template <typename T> void emit(T Value) { 114*03ce13f7SAndroid Build Coastguard Worker assert(hasEnsuredCapacity()); 115*03ce13f7SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void *>(Cursor), &Value, sizeof(T)); 116*03ce13f7SAndroid Build Coastguard Worker Cursor += sizeof(T); 117*03ce13f7SAndroid Build Coastguard Worker } 118*03ce13f7SAndroid Build Coastguard Worker load(intptr_t Position)119*03ce13f7SAndroid Build Coastguard Worker template <typename T> T load(intptr_t Position) const { 120*03ce13f7SAndroid Build Coastguard Worker assert(Position >= 0 && 121*03ce13f7SAndroid Build Coastguard Worker Position <= (size() - static_cast<intptr_t>(sizeof(T)))); 122*03ce13f7SAndroid Build Coastguard Worker T Value; 123*03ce13f7SAndroid Build Coastguard Worker memcpy(&Value, reinterpret_cast<void *>(Contents + Position), sizeof(T)); 124*03ce13f7SAndroid Build Coastguard Worker return Value; 125*03ce13f7SAndroid Build Coastguard Worker } 126*03ce13f7SAndroid Build Coastguard Worker store(intptr_t Position,T Value)127*03ce13f7SAndroid Build Coastguard Worker template <typename T> void store(intptr_t Position, T Value) { 128*03ce13f7SAndroid Build Coastguard Worker assert(Position >= 0 && 129*03ce13f7SAndroid Build Coastguard Worker Position <= (size() - static_cast<intptr_t>(sizeof(T)))); 130*03ce13f7SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void *>(Contents + Position), &Value, sizeof(T)); 131*03ce13f7SAndroid Build Coastguard Worker } 132*03ce13f7SAndroid Build Coastguard Worker /// @{ 133*03ce13f7SAndroid Build Coastguard Worker 134*03ce13f7SAndroid Build Coastguard Worker /// Emit a fixup at the current location. emitFixup(AssemblerFixup * Fixup)135*03ce13f7SAndroid Build Coastguard Worker void emitFixup(AssemblerFixup *Fixup) { Fixup->set_position(size()); } 136*03ce13f7SAndroid Build Coastguard Worker 137*03ce13f7SAndroid Build Coastguard Worker /// Get the size of the emitted code. size()138*03ce13f7SAndroid Build Coastguard Worker intptr_t size() const { return Cursor - Contents; } contents()139*03ce13f7SAndroid Build Coastguard Worker uintptr_t contents() const { return Contents; } 140*03ce13f7SAndroid Build Coastguard Worker 141*03ce13f7SAndroid Build Coastguard Worker /// To emit an instruction to the assembler buffer, the EnsureCapacity helper 142*03ce13f7SAndroid Build Coastguard Worker /// must be used to guarantee that the underlying data area is big enough to 143*03ce13f7SAndroid Build Coastguard Worker /// hold the emitted instruction. Usage: 144*03ce13f7SAndroid Build Coastguard Worker /// 145*03ce13f7SAndroid Build Coastguard Worker /// AssemblerBuffer buffer; 146*03ce13f7SAndroid Build Coastguard Worker /// AssemblerBuffer::EnsureCapacity ensured(&buffer); 147*03ce13f7SAndroid Build Coastguard Worker /// ... emit bytes for single instruction ... 148*03ce13f7SAndroid Build Coastguard Worker class EnsureCapacity { 149*03ce13f7SAndroid Build Coastguard Worker EnsureCapacity(const EnsureCapacity &) = delete; 150*03ce13f7SAndroid Build Coastguard Worker EnsureCapacity &operator=(const EnsureCapacity &) = delete; 151*03ce13f7SAndroid Build Coastguard Worker 152*03ce13f7SAndroid Build Coastguard Worker public: EnsureCapacity(AssemblerBuffer * Buffer)153*03ce13f7SAndroid Build Coastguard Worker explicit EnsureCapacity(AssemblerBuffer *Buffer) : Buffer(Buffer) { 154*03ce13f7SAndroid Build Coastguard Worker if (Buffer->cursor() >= Buffer->limit()) 155*03ce13f7SAndroid Build Coastguard Worker Buffer->extendCapacity(); 156*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::asserts()) 157*03ce13f7SAndroid Build Coastguard Worker validate(Buffer); 158*03ce13f7SAndroid Build Coastguard Worker } 159*03ce13f7SAndroid Build Coastguard Worker ~EnsureCapacity(); 160*03ce13f7SAndroid Build Coastguard Worker 161*03ce13f7SAndroid Build Coastguard Worker private: 162*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer *Buffer; 163*03ce13f7SAndroid Build Coastguard Worker intptr_t Gap = 0; 164*03ce13f7SAndroid Build Coastguard Worker 165*03ce13f7SAndroid Build Coastguard Worker void validate(AssemblerBuffer *Buffer); computeGap()166*03ce13f7SAndroid Build Coastguard Worker intptr_t computeGap() { return Buffer->capacity() - Buffer->size(); } 167*03ce13f7SAndroid Build Coastguard Worker }; 168*03ce13f7SAndroid Build Coastguard Worker 169*03ce13f7SAndroid Build Coastguard Worker bool HasEnsuredCapacity; hasEnsuredCapacity()170*03ce13f7SAndroid Build Coastguard Worker bool hasEnsuredCapacity() const { 171*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::asserts()) 172*03ce13f7SAndroid Build Coastguard Worker return HasEnsuredCapacity; 173*03ce13f7SAndroid Build Coastguard Worker // Disable the actual check in non-debug mode. 174*03ce13f7SAndroid Build Coastguard Worker return true; 175*03ce13f7SAndroid Build Coastguard Worker } 176*03ce13f7SAndroid Build Coastguard Worker 177*03ce13f7SAndroid Build Coastguard Worker /// Returns the position in the instruction stream. getPosition()178*03ce13f7SAndroid Build Coastguard Worker intptr_t getPosition() const { return Cursor - Contents; } 179*03ce13f7SAndroid Build Coastguard Worker 180*03ce13f7SAndroid Build Coastguard Worker /// Create and track a fixup in the current function. 181*03ce13f7SAndroid Build Coastguard Worker AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value); 182*03ce13f7SAndroid Build Coastguard Worker 183*03ce13f7SAndroid Build Coastguard Worker /// Create and track a textual fixup in the current function. 184*03ce13f7SAndroid Build Coastguard Worker AssemblerTextFixup *createTextFixup(const std::string &Text, 185*03ce13f7SAndroid Build Coastguard Worker size_t BytesUsed); 186*03ce13f7SAndroid Build Coastguard Worker 187*03ce13f7SAndroid Build Coastguard Worker /// Mark that an attempt was made to emit, but failed. Hence, in order to 188*03ce13f7SAndroid Build Coastguard Worker /// continue, one must emit a text fixup. setNeedsTextFixup()189*03ce13f7SAndroid Build Coastguard Worker void setNeedsTextFixup() { TextFixupNeeded = true; } resetNeedsTextFixup()190*03ce13f7SAndroid Build Coastguard Worker void resetNeedsTextFixup() { TextFixupNeeded = false; } 191*03ce13f7SAndroid Build Coastguard Worker 192*03ce13f7SAndroid Build Coastguard Worker /// Returns true if last emit failed and needs a text fixup. needsTextFixup()193*03ce13f7SAndroid Build Coastguard Worker bool needsTextFixup() const { return TextFixupNeeded; } 194*03ce13f7SAndroid Build Coastguard Worker 195*03ce13f7SAndroid Build Coastguard Worker /// Installs a created fixup, after it has been allocated. 196*03ce13f7SAndroid Build Coastguard Worker void installFixup(AssemblerFixup *F); 197*03ce13f7SAndroid Build Coastguard Worker fixups()198*03ce13f7SAndroid Build Coastguard Worker const FixupRefList &fixups() const { return Fixups; } 199*03ce13f7SAndroid Build Coastguard Worker setSize(intptr_t NewSize)200*03ce13f7SAndroid Build Coastguard Worker void setSize(intptr_t NewSize) { 201*03ce13f7SAndroid Build Coastguard Worker assert(NewSize <= size()); 202*03ce13f7SAndroid Build Coastguard Worker Cursor = Contents + NewSize; 203*03ce13f7SAndroid Build Coastguard Worker } 204*03ce13f7SAndroid Build Coastguard Worker 205*03ce13f7SAndroid Build Coastguard Worker private: 206*03ce13f7SAndroid Build Coastguard Worker /// The limit is set to kMinimumGap bytes before the end of the data area. 207*03ce13f7SAndroid Build Coastguard Worker /// This leaves enough space for the longest possible instruction and allows 208*03ce13f7SAndroid Build Coastguard Worker /// for a single, fast space check per instruction. 209*03ce13f7SAndroid Build Coastguard Worker static constexpr intptr_t kMinimumGap = 32; 210*03ce13f7SAndroid Build Coastguard Worker 211*03ce13f7SAndroid Build Coastguard Worker uintptr_t Contents; 212*03ce13f7SAndroid Build Coastguard Worker uintptr_t Cursor; 213*03ce13f7SAndroid Build Coastguard Worker uintptr_t Limit; 214*03ce13f7SAndroid Build Coastguard Worker // The member variable is named Assemblr to avoid hiding the class Assembler. 215*03ce13f7SAndroid Build Coastguard Worker Assembler &Assemblr; 216*03ce13f7SAndroid Build Coastguard Worker /// List of pool-allocated fixups relative to the current function. 217*03ce13f7SAndroid Build Coastguard Worker FixupRefList Fixups; 218*03ce13f7SAndroid Build Coastguard Worker // True if a textual fixup is needed, because the assembler was unable to 219*03ce13f7SAndroid Build Coastguard Worker // emit the last request. 220*03ce13f7SAndroid Build Coastguard Worker bool TextFixupNeeded; 221*03ce13f7SAndroid Build Coastguard Worker cursor()222*03ce13f7SAndroid Build Coastguard Worker uintptr_t cursor() const { return Cursor; } limit()223*03ce13f7SAndroid Build Coastguard Worker uintptr_t limit() const { return Limit; } capacity()224*03ce13f7SAndroid Build Coastguard Worker intptr_t capacity() const { 225*03ce13f7SAndroid Build Coastguard Worker assert(Limit >= Contents); 226*03ce13f7SAndroid Build Coastguard Worker return (Limit - Contents) + kMinimumGap; 227*03ce13f7SAndroid Build Coastguard Worker } 228*03ce13f7SAndroid Build Coastguard Worker 229*03ce13f7SAndroid Build Coastguard Worker /// Compute the limit based on the data area and the capacity. See description 230*03ce13f7SAndroid Build Coastguard Worker /// of kMinimumGap for the reasoning behind the value. computeLimit(uintptr_t Data,intptr_t Capacity)231*03ce13f7SAndroid Build Coastguard Worker static uintptr_t computeLimit(uintptr_t Data, intptr_t Capacity) { 232*03ce13f7SAndroid Build Coastguard Worker return Data + Capacity - kMinimumGap; 233*03ce13f7SAndroid Build Coastguard Worker } 234*03ce13f7SAndroid Build Coastguard Worker 235*03ce13f7SAndroid Build Coastguard Worker void extendCapacity(); 236*03ce13f7SAndroid Build Coastguard Worker }; 237*03ce13f7SAndroid Build Coastguard Worker 238*03ce13f7SAndroid Build Coastguard Worker class Assembler { 239*03ce13f7SAndroid Build Coastguard Worker Assembler() = delete; 240*03ce13f7SAndroid Build Coastguard Worker Assembler(const Assembler &) = delete; 241*03ce13f7SAndroid Build Coastguard Worker Assembler &operator=(const Assembler &) = delete; 242*03ce13f7SAndroid Build Coastguard Worker 243*03ce13f7SAndroid Build Coastguard Worker public: 244*03ce13f7SAndroid Build Coastguard Worker enum AssemblerKind { 245*03ce13f7SAndroid Build Coastguard Worker Asm_ARM32, 246*03ce13f7SAndroid Build Coastguard Worker Asm_MIPS32, 247*03ce13f7SAndroid Build Coastguard Worker Asm_X8632, 248*03ce13f7SAndroid Build Coastguard Worker Asm_X8664, 249*03ce13f7SAndroid Build Coastguard Worker }; 250*03ce13f7SAndroid Build Coastguard Worker 251*03ce13f7SAndroid Build Coastguard Worker virtual ~Assembler() = default; 252*03ce13f7SAndroid Build Coastguard Worker 253*03ce13f7SAndroid Build Coastguard Worker /// Allocate a chunk of bytes using the per-Assembler allocator. allocateBytes(size_t bytes)254*03ce13f7SAndroid Build Coastguard Worker uintptr_t allocateBytes(size_t bytes) { 255*03ce13f7SAndroid Build Coastguard Worker // For now, alignment is not related to NaCl bundle alignment, since the 256*03ce13f7SAndroid Build Coastguard Worker // buffer's GetPosition is relative to the base. So NaCl bundle alignment 257*03ce13f7SAndroid Build Coastguard Worker // checks can be relative to that base. Later, the buffer will be copied 258*03ce13f7SAndroid Build Coastguard Worker // out to a ".text" section (or an in memory-buffer that can be mprotect'ed 259*03ce13f7SAndroid Build Coastguard Worker // with executable permission), and that second buffer should be aligned 260*03ce13f7SAndroid Build Coastguard Worker // for NaCl. 261*03ce13f7SAndroid Build Coastguard Worker const size_t Alignment = 16; 262*03ce13f7SAndroid Build Coastguard Worker return reinterpret_cast<uintptr_t>(Allocator.Allocate(bytes, Alignment)); 263*03ce13f7SAndroid Build Coastguard Worker } 264*03ce13f7SAndroid Build Coastguard Worker 265*03ce13f7SAndroid Build Coastguard Worker /// Allocate data of type T using the per-Assembler allocator. allocate()266*03ce13f7SAndroid Build Coastguard Worker template <typename T> T *allocate() { return Allocator.Allocate<T>(); } 267*03ce13f7SAndroid Build Coastguard Worker 268*03ce13f7SAndroid Build Coastguard Worker /// Align the tail end of the function to the required target alignment. 269*03ce13f7SAndroid Build Coastguard Worker virtual void alignFunction() = 0; 270*03ce13f7SAndroid Build Coastguard Worker /// Align the tail end of the basic block to the required target alignment. alignCfgNode()271*03ce13f7SAndroid Build Coastguard Worker void alignCfgNode() { 272*03ce13f7SAndroid Build Coastguard Worker const SizeT Align = 1 << getBundleAlignLog2Bytes(); 273*03ce13f7SAndroid Build Coastguard Worker padWithNop(Utils::OffsetToAlignment(Buffer.getPosition(), Align)); 274*03ce13f7SAndroid Build Coastguard Worker } 275*03ce13f7SAndroid Build Coastguard Worker 276*03ce13f7SAndroid Build Coastguard Worker /// Add nop padding of a particular width to the current bundle. 277*03ce13f7SAndroid Build Coastguard Worker virtual void padWithNop(intptr_t Padding) = 0; 278*03ce13f7SAndroid Build Coastguard Worker 279*03ce13f7SAndroid Build Coastguard Worker virtual SizeT getBundleAlignLog2Bytes() const = 0; 280*03ce13f7SAndroid Build Coastguard Worker 281*03ce13f7SAndroid Build Coastguard Worker virtual const char *getAlignDirective() const = 0; 282*03ce13f7SAndroid Build Coastguard Worker virtual llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const = 0; 283*03ce13f7SAndroid Build Coastguard Worker 284*03ce13f7SAndroid Build Coastguard Worker /// Get the label for a CfgNode. 285*03ce13f7SAndroid Build Coastguard Worker virtual Label *getCfgNodeLabel(SizeT NodeNumber) = 0; 286*03ce13f7SAndroid Build Coastguard Worker /// Mark the current text location as the start of a CFG node. 287*03ce13f7SAndroid Build Coastguard Worker virtual void bindCfgNodeLabel(const CfgNode *Node) = 0; 288*03ce13f7SAndroid Build Coastguard Worker 289*03ce13f7SAndroid Build Coastguard Worker virtual bool fixupIsPCRel(FixupKind Kind) const = 0; 290*03ce13f7SAndroid Build Coastguard Worker 291*03ce13f7SAndroid Build Coastguard Worker /// Return a view of all the bytes of code for the current function. 292*03ce13f7SAndroid Build Coastguard Worker llvm::StringRef getBufferView() const; 293*03ce13f7SAndroid Build Coastguard Worker 294*03ce13f7SAndroid Build Coastguard Worker /// Return the value of the given type in the corresponding buffer. load(intptr_t Position)295*03ce13f7SAndroid Build Coastguard Worker template <typename T> T load(intptr_t Position) const { 296*03ce13f7SAndroid Build Coastguard Worker return Buffer.load<T>(Position); 297*03ce13f7SAndroid Build Coastguard Worker } 298*03ce13f7SAndroid Build Coastguard Worker store(intptr_t Position,T Value)299*03ce13f7SAndroid Build Coastguard Worker template <typename T> void store(intptr_t Position, T Value) { 300*03ce13f7SAndroid Build Coastguard Worker Buffer.store(Position, Value); 301*03ce13f7SAndroid Build Coastguard Worker } 302*03ce13f7SAndroid Build Coastguard Worker 303*03ce13f7SAndroid Build Coastguard Worker /// Emit a fixup at the current location. emitFixup(AssemblerFixup * Fixup)304*03ce13f7SAndroid Build Coastguard Worker void emitFixup(AssemblerFixup *Fixup) { Buffer.emitFixup(Fixup); } 305*03ce13f7SAndroid Build Coastguard Worker fixups()306*03ce13f7SAndroid Build Coastguard Worker const FixupRefList &fixups() const { return Buffer.fixups(); } 307*03ce13f7SAndroid Build Coastguard Worker createFixup(FixupKind Kind,const Constant * Value)308*03ce13f7SAndroid Build Coastguard Worker AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value) { 309*03ce13f7SAndroid Build Coastguard Worker return Buffer.createFixup(Kind, Value); 310*03ce13f7SAndroid Build Coastguard Worker } 311*03ce13f7SAndroid Build Coastguard Worker createTextFixup(const std::string & Text,size_t BytesUsed)312*03ce13f7SAndroid Build Coastguard Worker AssemblerTextFixup *createTextFixup(const std::string &Text, 313*03ce13f7SAndroid Build Coastguard Worker size_t BytesUsed) { 314*03ce13f7SAndroid Build Coastguard Worker return Buffer.createTextFixup(Text, BytesUsed); 315*03ce13f7SAndroid Build Coastguard Worker } 316*03ce13f7SAndroid Build Coastguard Worker 317*03ce13f7SAndroid Build Coastguard Worker void bindRelocOffset(RelocOffset *Offset); 318*03ce13f7SAndroid Build Coastguard Worker setNeedsTextFixup()319*03ce13f7SAndroid Build Coastguard Worker void setNeedsTextFixup() { Buffer.setNeedsTextFixup(); } resetNeedsTextFixup()320*03ce13f7SAndroid Build Coastguard Worker void resetNeedsTextFixup() { Buffer.resetNeedsTextFixup(); } 321*03ce13f7SAndroid Build Coastguard Worker needsTextFixup()322*03ce13f7SAndroid Build Coastguard Worker bool needsTextFixup() const { return Buffer.needsTextFixup(); } 323*03ce13f7SAndroid Build Coastguard Worker 324*03ce13f7SAndroid Build Coastguard Worker void emitIASBytes(GlobalContext *Ctx) const; getInternal()325*03ce13f7SAndroid Build Coastguard Worker bool getInternal() const { return IsInternal; } setInternal(bool Internal)326*03ce13f7SAndroid Build Coastguard Worker void setInternal(bool Internal) { IsInternal = Internal; } getFunctionName()327*03ce13f7SAndroid Build Coastguard Worker GlobalString getFunctionName() const { return FunctionName; } setFunctionName(GlobalString NewName)328*03ce13f7SAndroid Build Coastguard Worker void setFunctionName(GlobalString NewName) { FunctionName = NewName; } getBufferSize()329*03ce13f7SAndroid Build Coastguard Worker intptr_t getBufferSize() const { return Buffer.size(); } 330*03ce13f7SAndroid Build Coastguard Worker /// Roll back to a (smaller) size. setBufferSize(intptr_t NewSize)331*03ce13f7SAndroid Build Coastguard Worker void setBufferSize(intptr_t NewSize) { Buffer.setSize(NewSize); } setPreliminary(bool Value)332*03ce13f7SAndroid Build Coastguard Worker void setPreliminary(bool Value) { Preliminary = Value; } getPreliminary()333*03ce13f7SAndroid Build Coastguard Worker bool getPreliminary() const { return Preliminary; } 334*03ce13f7SAndroid Build Coastguard Worker getKind()335*03ce13f7SAndroid Build Coastguard Worker AssemblerKind getKind() const { return Kind; } 336*03ce13f7SAndroid Build Coastguard Worker 337*03ce13f7SAndroid Build Coastguard Worker protected: Assembler(AssemblerKind Kind)338*03ce13f7SAndroid Build Coastguard Worker explicit Assembler(AssemblerKind Kind) 339*03ce13f7SAndroid Build Coastguard Worker : Kind(Kind), Allocator(), Buffer(*this) {} 340*03ce13f7SAndroid Build Coastguard Worker 341*03ce13f7SAndroid Build Coastguard Worker private: 342*03ce13f7SAndroid Build Coastguard Worker const AssemblerKind Kind; 343*03ce13f7SAndroid Build Coastguard Worker 344*03ce13f7SAndroid Build Coastguard Worker using AssemblerAllocator = 345*03ce13f7SAndroid Build Coastguard Worker llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, /*SlabSize=*/32 * 1024>; 346*03ce13f7SAndroid Build Coastguard Worker AssemblerAllocator Allocator; 347*03ce13f7SAndroid Build Coastguard Worker 348*03ce13f7SAndroid Build Coastguard Worker /// FunctionName and IsInternal are transferred from the original Cfg object, 349*03ce13f7SAndroid Build Coastguard Worker /// since the Cfg object may be deleted by the time the assembler buffer is 350*03ce13f7SAndroid Build Coastguard Worker /// emitted. 351*03ce13f7SAndroid Build Coastguard Worker GlobalString FunctionName; 352*03ce13f7SAndroid Build Coastguard Worker bool IsInternal = false; 353*03ce13f7SAndroid Build Coastguard Worker /// Preliminary indicates whether a preliminary pass is being made for 354*03ce13f7SAndroid Build Coastguard Worker /// calculating bundle padding (Preliminary=true), versus the final pass where 355*03ce13f7SAndroid Build Coastguard Worker /// all changes to label bindings, label links, and relocation fixups are 356*03ce13f7SAndroid Build Coastguard Worker /// fully committed (Preliminary=false). 357*03ce13f7SAndroid Build Coastguard Worker bool Preliminary = false; 358*03ce13f7SAndroid Build Coastguard Worker 359*03ce13f7SAndroid Build Coastguard Worker /// Installs a created fixup, after it has been allocated. installFixup(AssemblerFixup * F)360*03ce13f7SAndroid Build Coastguard Worker void installFixup(AssemblerFixup *F) { Buffer.installFixup(F); } 361*03ce13f7SAndroid Build Coastguard Worker 362*03ce13f7SAndroid Build Coastguard Worker protected: 363*03ce13f7SAndroid Build Coastguard Worker // Buffer's constructor uses the Allocator, so it needs to appear after it. 364*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp): dependencies on construction order are a nice way of shooting 365*03ce13f7SAndroid Build Coastguard Worker // yourself in the foot. Fix this. 366*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer Buffer; 367*03ce13f7SAndroid Build Coastguard Worker }; 368*03ce13f7SAndroid Build Coastguard Worker 369*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 370*03ce13f7SAndroid Build Coastguard Worker 371*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEASSEMBLER_H_ 372