blob: a9516e869b05a0213e96557245d9ef270f513493 [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 Voung0faec4c2014-11-05 17:29:56 -080023#include "IceOperand.h"
Jan Voung8acded02014-09-22 18:02:25 -070024
25namespace Ice {
26
27static uintptr_t NewContents(Assembler &assembler, intptr_t capacity) {
28 uintptr_t result = assembler.AllocateBytes(capacity);
29 return result;
30}
31
Jan Voungf76fd372014-10-16 15:39:22 -070032#ifndef NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070033AssemblerBuffer::EnsureCapacity::EnsureCapacity(AssemblerBuffer *buffer) {
34 if (buffer->cursor() >= buffer->limit())
35 buffer->ExtendCapacity();
36 // In debug mode, we save the assembler buffer along with the gap
37 // size before we start emitting to the buffer. This allows us to
38 // check that any single generated instruction doesn't overflow the
39 // limit implied by the minimum gap size.
40 buffer_ = buffer;
41 gap_ = ComputeGap();
42 // Make sure that extending the capacity leaves a big enough gap
43 // for any kind of instruction.
44 assert(gap_ >= kMinimumGap);
45 // Mark the buffer as having ensured the capacity.
46 assert(!buffer->HasEnsuredCapacity()); // Cannot nest.
47 buffer->has_ensured_capacity_ = true;
48}
49
50AssemblerBuffer::EnsureCapacity::~EnsureCapacity() {
51 // Unmark the buffer, so we cannot emit after this.
52 buffer_->has_ensured_capacity_ = false;
53 // Make sure the generated instruction doesn't take up more
54 // space than the minimum gap.
55 intptr_t delta = gap_ - ComputeGap();
56 assert(delta <= kMinimumGap);
57}
Jan Voungf76fd372014-10-16 15:39:22 -070058#endif // !NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070059
60AssemblerBuffer::AssemblerBuffer(Assembler &assembler) : assembler_(assembler) {
61 const intptr_t OneKB = 1024;
62 static const intptr_t kInitialBufferCapacity = 4 * OneKB;
63 contents_ = NewContents(assembler_, kInitialBufferCapacity);
64 cursor_ = contents_;
65 limit_ = ComputeLimit(contents_, kInitialBufferCapacity);
Jan Voungf76fd372014-10-16 15:39:22 -070066#ifndef NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070067 has_ensured_capacity_ = false;
68 fixups_processed_ = false;
Jan Voungf76fd372014-10-16 15:39:22 -070069#endif // !NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -070070
71 // Verify internal state.
72 assert(Capacity() == kInitialBufferCapacity);
73 assert(Size() == 0);
74}
75
76AssemblerBuffer::~AssemblerBuffer() {}
77
Jan Voung8acded02014-09-22 18:02:25 -070078void AssemblerBuffer::ExtendCapacity() {
79 intptr_t old_size = Size();
80 intptr_t old_capacity = Capacity();
81 const intptr_t OneMB = 1 << 20;
82 intptr_t new_capacity = std::min(old_capacity * 2, old_capacity + OneMB);
83 if (new_capacity < old_capacity) {
84 // FATAL
85 llvm_unreachable("Unexpected overflow in AssemblerBuffer::ExtendCapacity");
86 }
87
88 // Allocate the new data area and copy contents of the old one to it.
89 uintptr_t new_contents = NewContents(assembler_, new_capacity);
90 memmove(reinterpret_cast<void *>(new_contents),
91 reinterpret_cast<void *>(contents_), old_size);
92
93 // Compute the relocation delta and switch to the new contents area.
94 intptr_t delta = new_contents - contents_;
95 contents_ = new_contents;
96
97 // Update the cursor and recompute the limit.
98 cursor_ += delta;
99 limit_ = ComputeLimit(new_contents, new_capacity);
100
101 // Verify internal state.
102 assert(Capacity() == new_capacity);
103 assert(Size() == old_size);
104}
105
Jan Voung08c3bcd2014-12-01 17:55:16 -0800106llvm::StringRef Assembler::getBufferView() const {
107 return llvm::StringRef(reinterpret_cast<const char *>(buffer_.contents()),
108 buffer_.Size());
109}
110
Jan Voung0faec4c2014-11-05 17:29:56 -0800111void Assembler::emitIASBytes(GlobalContext *Ctx) const {
112 Ostream &Str = Ctx->getStrEmit();
113 intptr_t EndPosition = buffer_.Size();
114 intptr_t CurPosition = 0;
115 const intptr_t FixupSize = 4;
116 for (AssemblerBuffer::FixupList::const_iterator
117 FixupI = buffer_.fixups_begin(),
118 FixupE = buffer_.fixups_end(); FixupI != FixupE; ++FixupI) {
119 AssemblerFixup *NextFixup = *FixupI;
120 intptr_t NextFixupLoc = NextFixup->position();
121 for (intptr_t i = CurPosition; i < NextFixupLoc; ++i) {
122 Str << "\t.byte 0x";
123 Str.write_hex(buffer_.Load<uint8_t>(i));
124 Str << "\n";
125 }
126 Str << "\t.long ";
127 const ConstantRelocatable *Reloc = NextFixup->value();
128 if (Reloc->getSuppressMangling())
129 Str << Reloc->getName();
130 else
131 Str << Ctx->mangleName(Reloc->getName());
132 if (Reloc->getOffset()) {
133 Str << " + " << Reloc->getOffset();
134 }
135 bool IsPCRel = NextFixup->kind() == FK_PcRel_4;
136 if (IsPCRel)
137 Str << " - (. + " << FixupSize << ")";
138 Str << "\n";
139 CurPosition = NextFixupLoc + FixupSize;
140 assert(CurPosition <= EndPosition);
141 }
142 // Handle any bytes that are not prefixed by a fixup.
143 for (intptr_t i = CurPosition; i < EndPosition; ++i) {
144 Str << "\t.byte 0x";
145 Str.write_hex(buffer_.Load<uint8_t>(i));
146 Str << "\n";
147 }
148}
149
Jan Voung8acded02014-09-22 18:02:25 -0700150} // end of namespace Ice