blob: 9c77dce75ef6747631300d818058b309faa2e736 [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
22/// This file implements the Assembler base class.
23///
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
Jan Voungec270732015-01-12 17:00:22 -080038AssemblerFixup *AssemblerBuffer::createFixup(FixupKind Kind,
39 const Constant *Value) {
40 AssemblerFixup *F =
John Portoaff4ccf2015-06-10 16:35:06 -070041 new (Assemblr.allocate<AssemblerFixup>()) AssemblerFixup();
Jan Voungec270732015-01-12 17:00:22 -080042 F->set_position(0);
43 F->set_kind(Kind);
44 F->set_value(Value);
John Portoaff4ccf2015-06-10 16:35:06 -070045 if (!Assemblr.getPreliminary())
46 Fixups.push_back(F);
Jan Voungec270732015-01-12 17:00:22 -080047 return F;
48}
49
Jim Stichnoth20b71f52015-06-24 15:52:24 -070050void AssemblerBuffer::EnsureCapacity::validate(AssemblerBuffer *buffer) {
Andrew Scull57e12682015-09-16 11:30:19 -070051 // In debug mode, we save the assembler buffer along with the gap size before
52 // we start emitting to the buffer. This allows us to check that any single
53 // generated instruction doesn't overflow the limit implied by the minimum
54 // gap size.
John Portoaff4ccf2015-06-10 16:35:06 -070055 Gap = computeGap();
Andrew Scull57e12682015-09-16 11:30:19 -070056 // Make sure that extending the capacity leaves a big enough gap for any kind
57 // of instruction.
John Portoaff4ccf2015-06-10 16:35:06 -070058 assert(Gap >= kMinimumGap);
Jan Voung8acded02014-09-22 18:02:25 -070059 // Mark the buffer as having ensured the capacity.
John Portoaff4ccf2015-06-10 16:35:06 -070060 assert(!buffer->hasEnsuredCapacity()); // Cannot nest.
61 buffer->HasEnsuredCapacity = true;
Jan Voung8acded02014-09-22 18:02:25 -070062}
63
64AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
65 // Unmark the buffer, so we cannot emit after this.
John Portoaff4ccf2015-06-10 16:35:06 -070066 Buffer->HasEnsuredCapacity = false;
Andrew Scull57e12682015-09-16 11:30:19 -070067 // Make sure the generated instruction doesn't take up more space than the
68 // minimum gap.
John Portoaff4ccf2015-06-10 16:35:06 -070069 intptr_t delta = Gap - computeGap();
Jim Stichnoth20b71f52015-06-24 15:52:24 -070070 (void)delta;
Jan Voung8acded02014-09-22 18:02:25 -070071 assert(delta <= kMinimumGap);
72}
Jan Voung8acded02014-09-22 18:02:25 -070073
John Portoaff4ccf2015-06-10 16:35:06 -070074AssemblerBuffer::AssemblerBuffer(Assembler &Asm) : Assemblr(Asm) {
Jan Voung8acded02014-09-22 18:02:25 -070075 const intptr_t OneKB = 1024;
76 static const intptr_t kInitialBufferCapacity = 4 * OneKB;
John Portoaff4ccf2015-06-10 16:35:06 -070077 Contents = NewContents(Assemblr, kInitialBufferCapacity);
78 Cursor = Contents;
79 Limit = computeLimit(Contents, kInitialBufferCapacity);
John Portoaff4ccf2015-06-10 16:35:06 -070080 HasEnsuredCapacity = false;
Jan Voung8acded02014-09-22 18:02:25 -070081
82 // Verify internal state.
John Portoaff4ccf2015-06-10 16:35:06 -070083 assert(capacity() == kInitialBufferCapacity);
84 assert(size() == 0);
Jan Voung8acded02014-09-22 18:02:25 -070085}
86
Jim Stichnotheafb56c2015-06-22 10:35:22 -070087AssemblerBuffer::~AssemblerBuffer() = default;
Jan Voung8acded02014-09-22 18:02:25 -070088
John Portoaff4ccf2015-06-10 16:35:06 -070089void AssemblerBuffer::extendCapacity() {
90 intptr_t old_size = size();
91 intptr_t old_capacity = capacity();
Jan Voung8acded02014-09-22 18:02:25 -070092 const intptr_t OneMB = 1 << 20;
93 intptr_t new_capacity = std::min(old_capacity * 2, old_capacity + OneMB);
94 if (new_capacity < old_capacity) {
Jan Voungec270732015-01-12 17:00:22 -080095 llvm::report_fatal_error(
96 "Unexpected overflow in AssemblerBuffer::ExtendCapacity");
Jan Voung8acded02014-09-22 18:02:25 -070097 }
98
99 // Allocate the new data area and copy contents of the old one to it.
John Portoaff4ccf2015-06-10 16:35:06 -0700100 uintptr_t new_contents = NewContents(Assemblr, new_capacity);
Jan Voung8acded02014-09-22 18:02:25 -0700101 memmove(reinterpret_cast<void *>(new_contents),
John Portoaff4ccf2015-06-10 16:35:06 -0700102 reinterpret_cast<void *>(Contents), old_size);
Jan Voung8acded02014-09-22 18:02:25 -0700103
104 // Compute the relocation delta and switch to the new contents area.
John Portoaff4ccf2015-06-10 16:35:06 -0700105 intptr_t delta = new_contents - Contents;
106 Contents = new_contents;
Jan Voung8acded02014-09-22 18:02:25 -0700107
108 // Update the cursor and recompute the limit.
John Portoaff4ccf2015-06-10 16:35:06 -0700109 Cursor += delta;
110 Limit = computeLimit(new_contents, new_capacity);
Jan Voung8acded02014-09-22 18:02:25 -0700111
112 // Verify internal state.
John Portoaff4ccf2015-06-10 16:35:06 -0700113 assert(capacity() == new_capacity);
114 assert(size() == old_size);
Jan Voung8acded02014-09-22 18:02:25 -0700115}
116
Jan Voung08c3bcd2014-12-01 17:55:16 -0800117llvm::StringRef Assembler::getBufferView() const {
John Portoaff4ccf2015-06-10 16:35:06 -0700118 return llvm::StringRef(reinterpret_cast<const char *>(Buffer.contents()),
119 Buffer.size());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800120}
121
Jan Voung0faec4c2014-11-05 17:29:56 -0800122void Assembler::emitIASBytes(GlobalContext *Ctx) const {
123 Ostream &Str = Ctx->getStrEmit();
John Portoaff4ccf2015-06-10 16:35:06 -0700124 intptr_t EndPosition = Buffer.size();
Jan Voung0faec4c2014-11-05 17:29:56 -0800125 intptr_t CurPosition = 0;
126 const intptr_t FixupSize = 4;
Jan Voungec270732015-01-12 17:00:22 -0800127 for (const AssemblerFixup *NextFixup : fixups()) {
Jan Voung0faec4c2014-11-05 17:29:56 -0800128 intptr_t NextFixupLoc = NextFixup->position();
129 for (intptr_t i = CurPosition; i < NextFixupLoc; ++i) {
130 Str << "\t.byte 0x";
John Portoaff4ccf2015-06-10 16:35:06 -0700131 Str.write_hex(Buffer.load<uint8_t>(i));
Jan Voung0faec4c2014-11-05 17:29:56 -0800132 Str << "\n";
133 }
134 Str << "\t.long ";
Jan Voungb7db1a52015-07-21 09:39:01 -0700135 // For PCRel fixups, we write the pc-offset from a symbol into the Buffer
Andrew Scull57e12682015-09-16 11:30:19 -0700136 // (e.g., -4), but we don't represent that in the fixup's offset. Otherwise
137 // the fixup holds the true offset, and so does the Buffer. Just load the
138 // offset from the buffer.
John Portoaff4ccf2015-06-10 16:35:06 -0700139 NextFixup->emit(Ctx, Buffer.load<RelocOffsetT>(NextFixupLoc));
Jan Voungec270732015-01-12 17:00:22 -0800140 if (fixupIsPCRel(NextFixup->kind()))
Jim Stichnoth927f7cc2015-03-19 23:23:00 -0700141 Str << " - .";
Jan Voung0faec4c2014-11-05 17:29:56 -0800142 Str << "\n";
143 CurPosition = NextFixupLoc + FixupSize;
144 assert(CurPosition <= EndPosition);
145 }
146 // Handle any bytes that are not prefixed by a fixup.
147 for (intptr_t i = CurPosition; i < EndPosition; ++i) {
148 Str << "\t.byte 0x";
John Portoaff4ccf2015-06-10 16:35:06 -0700149 Str.write_hex(Buffer.load<uint8_t>(i));
Jan Voung0faec4c2014-11-05 17:29:56 -0800150 Str << "\n";
151 }
152}
153
Jan Voung8acded02014-09-22 18:02:25 -0700154} // end of namespace Ice