blob: 88c35d7d6447b38b85dcbabeae591e2c9bc6fc8c [file] [log] [blame]
John Portoaff4ccf2015-06-10 16:35:06 -07001//===- subzero/src/IceAssembler.cpp - Assembler base class ----------------===//
Jan Voung8acded02014-09-22 18:02:25 -07002// 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
4// BSD-style license that can be found in the LICENSE file.
5//
6// Modified by the Subzero authors.
7//
Jan Voung33a5f412015-02-03 16:06:42 -08008// This is forked from Dart revision 39313.
9// Please update the revision if we merge back changes from Dart.
10// https://code.google.com/p/dart/wiki/GettingTheSource
11//
Jan Voungf76fd372014-10-16 15:39:22 -070012//===----------------------------------------------------------------------===//
Jan Voung8acded02014-09-22 18:02:25 -070013//
14// The Subzero Code Generator
15//
16// This file is distributed under the University of Illinois Open Source
17// License. See LICENSE.TXT for details.
18//
19//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -070020///
21/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080022/// \brief Implements the Assembler base class.
Andrew Scull9612d322015-07-06 14:53:25 -070023///
Jan Voung8acded02014-09-22 18:02:25 -070024//===----------------------------------------------------------------------===//
25
John Portoaff4ccf2015-06-10 16:35:06 -070026#include "IceAssembler.h"
John Porto67f8de92015-06-25 10:14:17 -070027
Jan Voung0faec4c2014-11-05 17:29:56 -080028#include "IceGlobalContext.h"
Jan Voung0faec4c2014-11-05 17:29:56 -080029#include "IceOperand.h"
Jan Voung8acded02014-09-22 18:02:25 -070030
31namespace Ice {
32
John Portoaff4ccf2015-06-10 16:35:06 -070033static uintptr_t NewContents(Assembler &Assemblr, intptr_t Capacity) {
34 uintptr_t Result = Assemblr.allocateBytes(Capacity);
35 return Result;
Jan Voung8acded02014-09-22 18:02:25 -070036}
37
Karl Schimpf67574d82015-12-08 15:37:00 -080038void Label::linkTo(const Assembler &Asm, intptr_t Pos) {
39 // We must not set the link until the position is absolutely known. This means
40 // not during the preliminary (sandboxing) pass, and not when the instruction
41 // needs a text fixup (hybrid iasm mode).
42 if (Asm.getPreliminary() || Asm.needsTextFixup())
43 return;
44 assert(!isBound());
45 Position = Pos + kWordSize;
46 assert(isLinked());
47}
48
Karl Schimpf2fee2a22015-10-22 08:19:26 -070049void AssemblerBuffer::installFixup(AssemblerFixup *F) {
Karl Schimpf2fee2a22015-10-22 08:19:26 -070050 if (!Assemblr.getPreliminary())
51 Fixups.push_back(F);
52}
53
Jan Voungec270732015-01-12 17:00:22 -080054AssemblerFixup *AssemblerBuffer::createFixup(FixupKind Kind,
55 const Constant *Value) {
56 AssemblerFixup *F =
John Portoaff4ccf2015-06-10 16:35:06 -070057 new (Assemblr.allocate<AssemblerFixup>()) AssemblerFixup();
Jan Voungec270732015-01-12 17:00:22 -080058 F->set_kind(Kind);
59 F->set_value(Value);
Karl Schimpf2fee2a22015-10-22 08:19:26 -070060 installFixup(F);
61 return F;
62}
63
64AssemblerTextFixup *AssemblerBuffer::createTextFixup(const std::string &Text,
65 size_t BytesUsed) {
66 AssemblerTextFixup *F = new (Assemblr.allocate<AssemblerTextFixup>())
67 AssemblerTextFixup(Text, BytesUsed);
68 installFixup(F);
Karl Schimpf82975ba2016-02-02 10:17:01 -080069 resetNeedsTextFixup();
Jan Voungec270732015-01-12 17:00:22 -080070 return F;
71}
72
Jim Stichnoth20b71f52015-06-24 15:52:24 -070073void AssemblerBuffer::EnsureCapacity::validate(AssemblerBuffer *buffer) {
Andrew Scull57e12682015-09-16 11:30:19 -070074 // In debug mode, we save the assembler buffer along with the gap size before
75 // we start emitting to the buffer. This allows us to check that any single
76 // generated instruction doesn't overflow the limit implied by the minimum
77 // gap size.
John Portoaff4ccf2015-06-10 16:35:06 -070078 Gap = computeGap();
Andrew Scull57e12682015-09-16 11:30:19 -070079 // Make sure that extending the capacity leaves a big enough gap for any kind
80 // of instruction.
John Portoaff4ccf2015-06-10 16:35:06 -070081 assert(Gap >= kMinimumGap);
Jan Voung8acded02014-09-22 18:02:25 -070082 // Mark the buffer as having ensured the capacity.
John Portoaff4ccf2015-06-10 16:35:06 -070083 assert(!buffer->hasEnsuredCapacity()); // Cannot nest.
84 buffer->HasEnsuredCapacity = true;
Jan Voung8acded02014-09-22 18:02:25 -070085}
86
87AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
88 // Unmark the buffer, so we cannot emit after this.
John Portoaff4ccf2015-06-10 16:35:06 -070089 Buffer->HasEnsuredCapacity = false;
Andrew Scull57e12682015-09-16 11:30:19 -070090 // Make sure the generated instruction doesn't take up more space than the
91 // minimum gap.
John Portoaff4ccf2015-06-10 16:35:06 -070092 intptr_t delta = Gap - computeGap();
Jim Stichnoth20b71f52015-06-24 15:52:24 -070093 (void)delta;
Jan Voung8acded02014-09-22 18:02:25 -070094 assert(delta <= kMinimumGap);
95}
Jan Voung8acded02014-09-22 18:02:25 -070096
John Portoaff4ccf2015-06-10 16:35:06 -070097AssemblerBuffer::AssemblerBuffer(Assembler &Asm) : Assemblr(Asm) {
Karl Schimpf2fee2a22015-10-22 08:19:26 -070098 constexpr intptr_t OneKB = 1024;
99 static constexpr intptr_t kInitialBufferCapacity = 4 * OneKB;
John Portoaff4ccf2015-06-10 16:35:06 -0700100 Contents = NewContents(Assemblr, kInitialBufferCapacity);
101 Cursor = Contents;
102 Limit = computeLimit(Contents, kInitialBufferCapacity);
John Portoaff4ccf2015-06-10 16:35:06 -0700103 HasEnsuredCapacity = false;
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700104 TextFixupNeeded = false;
Jan Voung8acded02014-09-22 18:02:25 -0700105
106 // Verify internal state.
John Portoaff4ccf2015-06-10 16:35:06 -0700107 assert(capacity() == kInitialBufferCapacity);
108 assert(size() == 0);
Jan Voung8acded02014-09-22 18:02:25 -0700109}
110
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700111AssemblerBuffer::~AssemblerBuffer() = default;
Jan Voung8acded02014-09-22 18:02:25 -0700112
John Portoaff4ccf2015-06-10 16:35:06 -0700113void AssemblerBuffer::extendCapacity() {
114 intptr_t old_size = size();
115 intptr_t old_capacity = capacity();
Karl Schimpf2fee2a22015-10-22 08:19:26 -0700116 constexpr intptr_t OneMB = 1 << 20;
Jan Voung8acded02014-09-22 18:02:25 -0700117 intptr_t new_capacity = std::min(old_capacity * 2, old_capacity + OneMB);
118 if (new_capacity < old_capacity) {
Jan Voungec270732015-01-12 17:00:22 -0800119 llvm::report_fatal_error(
120 "Unexpected overflow in AssemblerBuffer::ExtendCapacity");
Jan Voung8acded02014-09-22 18:02:25 -0700121 }
122
123 // Allocate the new data area and copy contents of the old one to it.
John Portoaff4ccf2015-06-10 16:35:06 -0700124 uintptr_t new_contents = NewContents(Assemblr, new_capacity);
Jan Voung8acded02014-09-22 18:02:25 -0700125 memmove(reinterpret_cast<void *>(new_contents),
John Portoaff4ccf2015-06-10 16:35:06 -0700126 reinterpret_cast<void *>(Contents), old_size);
Jan Voung8acded02014-09-22 18:02:25 -0700127
128 // Compute the relocation delta and switch to the new contents area.
John Portoaff4ccf2015-06-10 16:35:06 -0700129 intptr_t delta = new_contents - Contents;
130 Contents = new_contents;
Jan Voung8acded02014-09-22 18:02:25 -0700131
132 // Update the cursor and recompute the limit.
John Portoaff4ccf2015-06-10 16:35:06 -0700133 Cursor += delta;
134 Limit = computeLimit(new_contents, new_capacity);
Jan Voung8acded02014-09-22 18:02:25 -0700135
136 // Verify internal state.
John Portoaff4ccf2015-06-10 16:35:06 -0700137 assert(capacity() == new_capacity);
138 assert(size() == old_size);
Jan Voung8acded02014-09-22 18:02:25 -0700139}
140
Jan Voung08c3bcd2014-12-01 17:55:16 -0800141llvm::StringRef Assembler::getBufferView() const {
John Portoaff4ccf2015-06-10 16:35:06 -0700142 return llvm::StringRef(reinterpret_cast<const char *>(Buffer.contents()),
143 Buffer.size());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800144}
145
John Portodc619252016-02-10 15:57:16 -0800146void Assembler::bindRelocOffset(RelocOffset *Offset) {
147 if (!getPreliminary()) {
148 Offset->setOffset(Buffer.getPosition());
149 }
150}
151
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700152void Assembler::emitIASBytes(GlobalContext *Ctx) const {
Jan Voung0faec4c2014-11-05 17:29:56 -0800153 Ostream &Str = Ctx->getStrEmit();
John Portoaff4ccf2015-06-10 16:35:06 -0700154 intptr_t EndPosition = Buffer.size();
Jan Voung0faec4c2014-11-05 17:29:56 -0800155 intptr_t CurPosition = 0;
Jan Voungec270732015-01-12 17:00:22 -0800156 for (const AssemblerFixup *NextFixup : fixups()) {
Jan Voung0faec4c2014-11-05 17:29:56 -0800157 intptr_t NextFixupLoc = NextFixup->position();
158 for (intptr_t i = CurPosition; i < NextFixupLoc; ++i) {
159 Str << "\t.byte 0x";
John Portoaff4ccf2015-06-10 16:35:06 -0700160 Str.write_hex(Buffer.load<uint8_t>(i));
Jan Voung0faec4c2014-11-05 17:29:56 -0800161 Str << "\n";
162 }
Karl Schimpfe4289e22015-10-27 15:16:27 -0700163 CurPosition = NextFixupLoc + NextFixup->emit(Ctx, *this);
Jan Voung0faec4c2014-11-05 17:29:56 -0800164 assert(CurPosition <= EndPosition);
165 }
166 // Handle any bytes that are not prefixed by a fixup.
167 for (intptr_t i = CurPosition; i < EndPosition; ++i) {
168 Str << "\t.byte 0x";
John Portoaff4ccf2015-06-10 16:35:06 -0700169 Str.write_hex(Buffer.load<uint8_t>(i));
Jan Voung0faec4c2014-11-05 17:29:56 -0800170 Str << "\n";
171 }
172}
173
Jan Voung8acded02014-09-22 18:02:25 -0700174} // end of namespace Ice