blob: b0bd297f057db71e178e6307261781ab9750b0d3 [file] [log] [blame]
Jan Voungf76fd372014-10-16 15:39:22 -07001//===- subzero/src/assembler.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 Voungf76fd372014-10-16 15:39:22 -07008//===----------------------------------------------------------------------===//
Jan Voung8acded02014-09-22 18:02:25 -07009//
10// The Subzero Code Generator
11//
12// This file is distributed under the University of Illinois Open Source
13// License. See LICENSE.TXT for details.
14//
15//===----------------------------------------------------------------------===//
16//
17// This file implements the Assembler class.
18//
19//===----------------------------------------------------------------------===//
20
21#include "assembler.h"
Jan Voung0faec4c2014-11-05 17:29:56 -080022#include "IceGlobalContext.h"
Jan Voung8acded02014-09-22 18:02:25 -070023#include "IceMemoryRegion.h"
Jan Voung0faec4c2014-11-05 17:29:56 -080024#include "IceOperand.h"
Jan Voung8acded02014-09-22 18:02:25 -070025
26namespace Ice {
27
28static uintptr_t NewContents(Assembler &assembler, intptr_t capacity) {
29 uintptr_t result = assembler.AllocateBytes(capacity);
30 return result;
31}
32
Jan Voungf76fd372014-10-16 15:39:22 -070033#ifndef NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070034AssemblerBuffer::EnsureCapacity::EnsureCapacity(AssemblerBuffer *buffer) {
35 if (buffer->cursor() >= buffer->limit())
36 buffer->ExtendCapacity();
37 // In debug mode, we save the assembler buffer along with the gap
38 // size before we start emitting to the buffer. This allows us to
39 // check that any single generated instruction doesn't overflow the
40 // limit implied by the minimum gap size.
41 buffer_ = buffer;
42 gap_ = ComputeGap();
43 // Make sure that extending the capacity leaves a big enough gap
44 // for any kind of instruction.
45 assert(gap_ >= kMinimumGap);
46 // Mark the buffer as having ensured the capacity.
47 assert(!buffer->HasEnsuredCapacity()); // Cannot nest.
48 buffer->has_ensured_capacity_ = true;
49}
50
51AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
52 // Unmark the buffer, so we cannot emit after this.
53 buffer_->has_ensured_capacity_ = false;
54 // Make sure the generated instruction doesn't take up more
55 // space than the minimum gap.
56 intptr_t delta = gap_ - ComputeGap();
57 assert(delta <= kMinimumGap);
58}
Jan Voungf76fd372014-10-16 15:39:22 -070059#endif // !NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070060
61AssemblerBuffer::AssemblerBuffer(Assembler &assembler) : assembler_(assembler) {
62 const intptr_t OneKB = 1024;
63 static const intptr_t kInitialBufferCapacity = 4 * OneKB;
64 contents_ = NewContents(assembler_, kInitialBufferCapacity);
65 cursor_ = contents_;
66 limit_ = ComputeLimit(contents_, kInitialBufferCapacity);
Jan Voungf76fd372014-10-16 15:39:22 -070067#ifndef NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070068 has_ensured_capacity_ = false;
69 fixups_processed_ = false;
Jan Voungf76fd372014-10-16 15:39:22 -070070#endif // !NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070071
72 // Verify internal state.
73 assert(Capacity() == kInitialBufferCapacity);
74 assert(Size() == 0);
75}
76
77AssemblerBuffer::~AssemblerBuffer() {}
78
Jan Voung8acded02014-09-22 18:02:25 -070079void AssemblerBuffer::ProcessFixups(const MemoryRegion &region) {
80 for (SizeT I = 0; I < fixups_.size(); ++I) {
81 AssemblerFixup *fixup = fixups_[I];
82 fixup->Process(region, fixup->position());
83 }
84}
85
86void AssemblerBuffer::FinalizeInstructions(const MemoryRegion &instructions) {
87 // Copy the instructions from the buffer.
88 MemoryRegion from(reinterpret_cast<void *>(contents()), Size());
89 instructions.CopyFrom(0, from);
90
91 // Process fixups in the instructions.
92 ProcessFixups(instructions);
Jan Voungf76fd372014-10-16 15:39:22 -070093#ifndef NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070094 fixups_processed_ = true;
Jan Voungf76fd372014-10-16 15:39:22 -070095#endif // !NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070096}
97
98void AssemblerBuffer::ExtendCapacity() {
99 intptr_t old_size = Size();
100 intptr_t old_capacity = Capacity();
101 const intptr_t OneMB = 1 << 20;
102 intptr_t new_capacity = std::min(old_capacity * 2, old_capacity + OneMB);
103 if (new_capacity < old_capacity) {
104 // FATAL
105 llvm_unreachable("Unexpected overflow in AssemblerBuffer::ExtendCapacity");
106 }
107
108 // Allocate the new data area and copy contents of the old one to it.
109 uintptr_t new_contents = NewContents(assembler_, new_capacity);
110 memmove(reinterpret_cast<void *>(new_contents),
111 reinterpret_cast<void *>(contents_), old_size);
112
113 // Compute the relocation delta and switch to the new contents area.
114 intptr_t delta = new_contents - contents_;
115 contents_ = new_contents;
116
117 // Update the cursor and recompute the limit.
118 cursor_ += delta;
119 limit_ = ComputeLimit(new_contents, new_capacity);
120
121 // Verify internal state.
122 assert(Capacity() == new_capacity);
123 assert(Size() == old_size);
124}
125
Jan Voung0faec4c2014-11-05 17:29:56 -0800126void Assembler::emitIASBytes(GlobalContext *Ctx) const {
127 Ostream &Str = Ctx->getStrEmit();
128 intptr_t EndPosition = buffer_.Size();
129 intptr_t CurPosition = 0;
130 const intptr_t FixupSize = 4;
131 for (AssemblerBuffer::FixupList::const_iterator
132 FixupI = buffer_.fixups_begin(),
133 FixupE = buffer_.fixups_end(); FixupI != FixupE; ++FixupI) {
134 AssemblerFixup *NextFixup = *FixupI;
135 intptr_t NextFixupLoc = NextFixup->position();
136 for (intptr_t i = CurPosition; i < NextFixupLoc; ++i) {
137 Str << "\t.byte 0x";
138 Str.write_hex(buffer_.Load<uint8_t>(i));
139 Str << "\n";
140 }
141 Str << "\t.long ";
142 const ConstantRelocatable *Reloc = NextFixup->value();
143 if (Reloc->getSuppressMangling())
144 Str << Reloc->getName();
145 else
146 Str << Ctx->mangleName(Reloc->getName());
147 if (Reloc->getOffset()) {
148 Str << " + " << Reloc->getOffset();
149 }
150 bool IsPCRel = NextFixup->kind() == FK_PcRel_4;
151 if (IsPCRel)
152 Str << " - (. + " << FixupSize << ")";
153 Str << "\n";
154 CurPosition = NextFixupLoc + FixupSize;
155 assert(CurPosition <= EndPosition);
156 }
157 // Handle any bytes that are not prefixed by a fixup.
158 for (intptr_t i = CurPosition; i < EndPosition; ++i) {
159 Str << "\t.byte 0x";
160 Str.write_hex(buffer_.Load<uint8_t>(i));
161 Str << "\n";
162 }
163}
164
Jan Voung8acded02014-09-22 18:02:25 -0700165} // end of namespace Ice