code_generator.h revision c32e770f21540e4e9eda6dc7f770e745d33f1b9f
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 18#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 19 20#include "base/bit_field.h" 21#include "globals.h" 22#include "instruction_set.h" 23#include "memory_region.h" 24#include "nodes.h" 25#include "utils/assembler.h" 26 27namespace art { 28 29static size_t constexpr kVRegSize = 4; 30 31class DexCompilationUnit; 32 33class CodeAllocator { 34 public: 35 CodeAllocator() { } 36 virtual ~CodeAllocator() { } 37 38 virtual uint8_t* Allocate(size_t size) = 0; 39 40 private: 41 DISALLOW_COPY_AND_ASSIGN(CodeAllocator); 42}; 43 44struct PcInfo { 45 uint32_t dex_pc; 46 uintptr_t native_pc; 47}; 48 49/** 50 * A Location is an abstraction over the potential location 51 * of an instruction. It could be in register or stack. 52 */ 53class Location : public ValueObject { 54 public: 55 enum Kind { 56 kInvalid = 0, 57 kStackSlot = 1, // Word size slot. 58 kDoubleStackSlot = 2, // 64bit stack slot. 59 kRegister = 3, 60 // On 32bits architectures, quick can pass a long where the 61 // low bits are in the last parameter register, and the high 62 // bits are in a stack slot. The kQuickParameter kind is for 63 // handling this special case. 64 kQuickParameter = 4, 65 }; 66 67 Location() : value_(kInvalid) { 68 DCHECK(!IsValid()); 69 } 70 71 Location(const Location& other) : ValueObject(), value_(other.value_) {} 72 73 Location& operator=(const Location& other) { 74 value_ = other.value_; 75 return *this; 76 } 77 78 bool IsValid() const { 79 return value_ != kInvalid; 80 } 81 82 // Register locations. 83 static Location RegisterLocation(ManagedRegister reg) { 84 return Location(kRegister, reg.RegId()); 85 } 86 87 bool IsRegister() const { 88 return GetKind() == kRegister; 89 } 90 91 ManagedRegister reg() const { 92 DCHECK(IsRegister()); 93 return static_cast<ManagedRegister>(GetPayload()); 94 } 95 96 static uword EncodeStackIndex(intptr_t stack_index) { 97 DCHECK(-kStackIndexBias <= stack_index); 98 DCHECK(stack_index < kStackIndexBias); 99 return static_cast<uword>(kStackIndexBias + stack_index); 100 } 101 102 static Location StackSlot(intptr_t stack_index) { 103 uword payload = EncodeStackIndex(stack_index); 104 Location loc(kStackSlot, payload); 105 // Ensure that sign is preserved. 106 DCHECK_EQ(loc.GetStackIndex(), stack_index); 107 return loc; 108 } 109 110 bool IsStackSlot() const { 111 return GetKind() == kStackSlot; 112 } 113 114 static Location DoubleStackSlot(intptr_t stack_index) { 115 uword payload = EncodeStackIndex(stack_index); 116 Location loc(kDoubleStackSlot, payload); 117 // Ensure that sign is preserved. 118 DCHECK_EQ(loc.GetStackIndex(), stack_index); 119 return loc; 120 } 121 122 bool IsDoubleStackSlot() const { 123 return GetKind() == kDoubleStackSlot; 124 } 125 126 intptr_t GetStackIndex() const { 127 DCHECK(IsStackSlot() || IsDoubleStackSlot()); 128 // Decode stack index manually to preserve sign. 129 return GetPayload() - kStackIndexBias; 130 } 131 132 intptr_t GetHighStackIndex(uintptr_t word_size) const { 133 DCHECK(IsDoubleStackSlot()); 134 // Decode stack index manually to preserve sign. 135 return GetPayload() - kStackIndexBias + word_size; 136 } 137 138 static Location QuickParameter(uint32_t parameter_index) { 139 return Location(kQuickParameter, parameter_index); 140 } 141 142 uint32_t GetQuickParameterIndex() const { 143 DCHECK(IsQuickParameter()); 144 return GetPayload(); 145 } 146 147 bool IsQuickParameter() const { 148 return GetKind() == kQuickParameter; 149 } 150 151 arm::ArmManagedRegister AsArm() const; 152 x86::X86ManagedRegister AsX86() const; 153 154 Kind GetKind() const { 155 return KindField::Decode(value_); 156 } 157 158 bool Equals(Location other) const { 159 return value_ == other.value_; 160 } 161 162 const char* DebugString() const { 163 switch (GetKind()) { 164 case kInvalid: return "?"; 165 case kRegister: return "R"; 166 case kStackSlot: return "S"; 167 case kDoubleStackSlot: return "DS"; 168 case kQuickParameter: return "Q"; 169 } 170 return "?"; 171 } 172 173 private: 174 // Number of bits required to encode Kind value. 175 static constexpr uint32_t kBitsForKind = 4; 176 static constexpr uint32_t kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind; 177 178 explicit Location(uword value) : value_(value) {} 179 180 Location(Kind kind, uword payload) 181 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {} 182 183 uword GetPayload() const { 184 return PayloadField::Decode(value_); 185 } 186 187 typedef BitField<Kind, 0, kBitsForKind> KindField; 188 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; 189 190 // Layout for stack slots. 191 static const intptr_t kStackIndexBias = 192 static_cast<intptr_t>(1) << (kBitsForPayload - 1); 193 194 // Location either contains kind and payload fields or a tagged handle for 195 // a constant locations. Values of enumeration Kind are selected in such a 196 // way that none of them can be interpreted as a kConstant tag. 197 uword value_; 198}; 199 200/** 201 * The code generator computes LocationSummary for each instruction so that 202 * the instruction itself knows what code to generate: where to find the inputs 203 * and where to place the result. 204 * 205 * The intent is to have the code for generating the instruction independent of 206 * register allocation. A register allocator just has to provide a LocationSummary. 207 */ 208class LocationSummary : public ArenaObject { 209 public: 210 explicit LocationSummary(HInstruction* instruction) 211 : inputs(instruction->GetBlock()->GetGraph()->GetArena(), instruction->InputCount()), 212 temps(instruction->GetBlock()->GetGraph()->GetArena(), 0) { 213 inputs.SetSize(instruction->InputCount()); 214 for (size_t i = 0; i < instruction->InputCount(); i++) { 215 inputs.Put(i, Location()); 216 } 217 } 218 219 void SetInAt(uint32_t at, Location location) { 220 inputs.Put(at, location); 221 } 222 223 Location InAt(uint32_t at) const { 224 return inputs.Get(at); 225 } 226 227 void SetOut(Location location) { 228 output = Location(location); 229 } 230 231 void AddTemp(Location location) { 232 temps.Add(location); 233 } 234 235 Location GetTemp(uint32_t at) const { 236 return temps.Get(at); 237 } 238 239 Location Out() const { return output; } 240 241 private: 242 GrowableArray<Location> inputs; 243 GrowableArray<Location> temps; 244 Location output; 245 246 DISALLOW_COPY_AND_ASSIGN(LocationSummary); 247}; 248 249class CodeGenerator : public ArenaObject { 250 public: 251 // Compiles the graph to executable instructions. Returns whether the compilation 252 // succeeded. 253 void Compile(CodeAllocator* allocator); 254 static CodeGenerator* Create(ArenaAllocator* allocator, 255 HGraph* graph, 256 InstructionSet instruction_set); 257 258 HGraph* GetGraph() const { return graph_; } 259 260 Label* GetLabelOf(HBasicBlock* block) const; 261 bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const; 262 263 virtual void GenerateFrameEntry() = 0; 264 virtual void GenerateFrameExit() = 0; 265 virtual void Bind(Label* label) = 0; 266 virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0; 267 virtual HGraphVisitor* GetLocationBuilder() = 0; 268 virtual HGraphVisitor* GetInstructionVisitor() = 0; 269 virtual Assembler* GetAssembler() = 0; 270 virtual size_t GetWordSize() const = 0; 271 272 uint32_t GetFrameSize() const { return frame_size_; } 273 void SetFrameSize(uint32_t size) { frame_size_ = size; } 274 uint32_t GetCoreSpillMask() const { return core_spill_mask_; } 275 276 void RecordPcInfo(uint32_t dex_pc) { 277 struct PcInfo pc_info; 278 pc_info.dex_pc = dex_pc; 279 pc_info.native_pc = GetAssembler()->CodeSize(); 280 pc_infos_.Add(pc_info); 281 } 282 283 void BuildMappingTable(std::vector<uint8_t>* vector) const; 284 void BuildVMapTable(std::vector<uint8_t>* vector) const; 285 void BuildNativeGCMap( 286 std::vector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const; 287 288 protected: 289 explicit CodeGenerator(HGraph* graph) 290 : frame_size_(0), 291 graph_(graph), 292 block_labels_(graph->GetArena(), 0), 293 pc_infos_(graph->GetArena(), 32) { 294 block_labels_.SetSize(graph->GetBlocks()->Size()); 295 } 296 ~CodeGenerator() { } 297 298 // Frame size required for this method. 299 uint32_t frame_size_; 300 uint32_t core_spill_mask_; 301 302 private: 303 void InitLocations(HInstruction* instruction); 304 void CompileBlock(HBasicBlock* block); 305 306 HGraph* const graph_; 307 308 // Labels for each block that will be compiled. 309 GrowableArray<Label> block_labels_; 310 GrowableArray<PcInfo> pc_infos_; 311 312 DISALLOW_COPY_AND_ASSIGN(CodeGenerator); 313}; 314 315template <typename T> 316class CallingConvention { 317 public: 318 CallingConvention(const T* registers, int number_of_registers) 319 : registers_(registers), number_of_registers_(number_of_registers) {} 320 321 size_t GetNumberOfRegisters() const { return number_of_registers_; } 322 323 T GetRegisterAt(size_t index) const { 324 DCHECK_LT(index, number_of_registers_); 325 return registers_[index]; 326 } 327 328 uint8_t GetStackOffsetOf(size_t index, size_t word_size) const { 329 // We still reserve the space for parameters passed by registers. 330 // Add word_size for the method pointer. 331 return index * kVRegSize + word_size; 332 } 333 334 private: 335 const T* registers_; 336 const size_t number_of_registers_; 337 338 DISALLOW_COPY_AND_ASSIGN(CallingConvention); 339}; 340 341} // namespace art 342 343#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 344