1 /* 2 * Copyright (C) 2012 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_LLVM_IR_BUILDER_H_ 18 #define ART_COMPILER_LLVM_IR_BUILDER_H_ 19 20 #include "backend_types.h" 21 #include "dex/compiler_enums.h" 22 #include "intrinsic_helper.h" 23 #include "md_builder.h" 24 #include "runtime_support_builder.h" 25 #include "runtime_support_llvm_func.h" 26 27 #include <llvm/IR/Constants.h> 28 #include <llvm/IR/DerivedTypes.h> 29 #include <llvm/IR/IRBuilder.h> 30 #include <llvm/IR/LLVMContext.h> 31 #include <llvm/IR/Type.h> 32 #include <llvm/Support/NoFolder.h> 33 34 #include <stdint.h> 35 36 37 namespace art { 38 namespace llvm { 39 40 class InserterWithDexOffset : public ::llvm::IRBuilderDefaultInserter<true> { 41 public: InserterWithDexOffset()42 InserterWithDexOffset() : node_(NULL) {} 43 InsertHelper(::llvm::Instruction * I,const::llvm::Twine & Name,::llvm::BasicBlock * BB,::llvm::BasicBlock::iterator InsertPt)44 void InsertHelper(::llvm::Instruction *I, const ::llvm::Twine &Name, 45 ::llvm::BasicBlock *BB, 46 ::llvm::BasicBlock::iterator InsertPt) const { 47 ::llvm::IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt); 48 if (node_ != NULL) { 49 I->setMetadata("DexOff", node_); 50 } 51 } 52 SetDexOffset(::llvm::MDNode * node)53 void SetDexOffset(::llvm::MDNode* node) { 54 node_ = node; 55 } 56 private: 57 ::llvm::MDNode* node_; 58 }; 59 60 typedef ::llvm::IRBuilder<true, ::llvm::ConstantFolder, InserterWithDexOffset> LLVMIRBuilder; 61 // NOTE: Here we define our own LLVMIRBuilder type alias, so that we can 62 // switch "preserveNames" template parameter easily. 63 64 65 class IRBuilder : public LLVMIRBuilder { 66 public: 67 //-------------------------------------------------------------------------- 68 // General 69 //-------------------------------------------------------------------------- 70 71 IRBuilder(::llvm::LLVMContext& context, ::llvm::Module& module, 72 IntrinsicHelper& intrinsic_helper); 73 74 75 //-------------------------------------------------------------------------- 76 // Extend load & store for TBAA 77 //-------------------------------------------------------------------------- 78 CreateLoad(::llvm::Value * ptr,::llvm::MDNode * tbaa_info)79 ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, ::llvm::MDNode* tbaa_info) { 80 ::llvm::LoadInst* inst = LLVMIRBuilder::CreateLoad(ptr); 81 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info); 82 return inst; 83 } 84 CreateStore(::llvm::Value * val,::llvm::Value * ptr,::llvm::MDNode * tbaa_info)85 ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, ::llvm::MDNode* tbaa_info) { 86 ::llvm::StoreInst* inst = LLVMIRBuilder::CreateStore(val, ptr); 87 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info); 88 return inst; 89 } 90 91 ::llvm::AtomicCmpXchgInst* CreateAtomicCmpXchgInst(::llvm::Value * ptr,::llvm::Value * cmp,::llvm::Value * val,::llvm::MDNode * tbaa_info)92 CreateAtomicCmpXchgInst(::llvm::Value* ptr, ::llvm::Value* cmp, ::llvm::Value* val, 93 ::llvm::MDNode* tbaa_info) { 94 ::llvm::AtomicCmpXchgInst* inst = 95 LLVMIRBuilder::CreateAtomicCmpXchg(ptr, cmp, val, ::llvm::Acquire); 96 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info); 97 return inst; 98 } 99 100 //-------------------------------------------------------------------------- 101 // Extend memory barrier 102 //-------------------------------------------------------------------------- CreateMemoryBarrier(MemBarrierKind barrier_kind)103 void CreateMemoryBarrier(MemBarrierKind barrier_kind) { 104 #if ANDROID_SMP 105 // TODO: select atomic ordering according to given barrier kind. 106 CreateFence(::llvm::SequentiallyConsistent); 107 #endif 108 } 109 110 //-------------------------------------------------------------------------- 111 // TBAA 112 //-------------------------------------------------------------------------- 113 114 // TODO: After we design the non-special TBAA info, re-design the TBAA interface. CreateLoad(::llvm::Value * ptr,TBAASpecialType special_ty)115 ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty) { 116 return CreateLoad(ptr, mdb_.GetTBAASpecialType(special_ty)); 117 } 118 CreateStore(::llvm::Value * val,::llvm::Value * ptr,TBAASpecialType special_ty)119 ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, TBAASpecialType special_ty) { 120 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!"; 121 return CreateStore(val, ptr, mdb_.GetTBAASpecialType(special_ty)); 122 } 123 CreateLoad(::llvm::Value * ptr,TBAASpecialType special_ty,JType j_ty)124 ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty, JType j_ty) { 125 return CreateLoad(ptr, mdb_.GetTBAAMemoryJType(special_ty, j_ty)); 126 } 127 CreateStore(::llvm::Value * val,::llvm::Value * ptr,TBAASpecialType special_ty,JType j_ty)128 ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, 129 TBAASpecialType special_ty, JType j_ty) { 130 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!"; 131 return CreateStore(val, ptr, mdb_.GetTBAAMemoryJType(special_ty, j_ty)); 132 } 133 LoadFromObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Type * type,TBAASpecialType special_ty)134 ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr, 135 int64_t offset, 136 ::llvm::Type* type, 137 TBAASpecialType special_ty) { 138 return LoadFromObjectOffset(object_addr, offset, type, mdb_.GetTBAASpecialType(special_ty)); 139 } 140 StoreToObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * new_value,TBAASpecialType special_ty)141 void StoreToObjectOffset(::llvm::Value* object_addr, 142 int64_t offset, 143 ::llvm::Value* new_value, 144 TBAASpecialType special_ty) { 145 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!"; 146 StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAASpecialType(special_ty)); 147 } 148 LoadFromObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Type * type,TBAASpecialType special_ty,JType j_ty)149 ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr, 150 int64_t offset, 151 ::llvm::Type* type, 152 TBAASpecialType special_ty, JType j_ty) { 153 return LoadFromObjectOffset(object_addr, offset, type, mdb_.GetTBAAMemoryJType(special_ty, j_ty)); 154 } 155 StoreToObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * new_value,TBAASpecialType special_ty,JType j_ty)156 void StoreToObjectOffset(::llvm::Value* object_addr, 157 int64_t offset, 158 ::llvm::Value* new_value, 159 TBAASpecialType special_ty, JType j_ty) { 160 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!"; 161 StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAAMemoryJType(special_ty, j_ty)); 162 } 163 164 ::llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * cmp_value,::llvm::Value * new_value,TBAASpecialType special_ty)165 CompareExchangeObjectOffset(::llvm::Value* object_addr, 166 int64_t offset, 167 ::llvm::Value* cmp_value, 168 ::llvm::Value* new_value, 169 TBAASpecialType special_ty) { 170 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!"; 171 return CompareExchangeObjectOffset(object_addr, offset, cmp_value, new_value, 172 mdb_.GetTBAASpecialType(special_ty)); 173 } 174 SetTBAA(::llvm::Instruction * inst,TBAASpecialType special_ty)175 void SetTBAA(::llvm::Instruction* inst, TBAASpecialType special_ty) { 176 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, mdb_.GetTBAASpecialType(special_ty)); 177 } 178 179 180 //-------------------------------------------------------------------------- 181 // Static Branch Prediction 182 //-------------------------------------------------------------------------- 183 184 // Import the orignal conditional branch 185 using LLVMIRBuilder::CreateCondBr; CreateCondBr(::llvm::Value * cond,::llvm::BasicBlock * true_bb,::llvm::BasicBlock * false_bb,ExpectCond expect)186 ::llvm::BranchInst* CreateCondBr(::llvm::Value *cond, 187 ::llvm::BasicBlock* true_bb, 188 ::llvm::BasicBlock* false_bb, 189 ExpectCond expect) { 190 ::llvm::BranchInst* branch_inst = CreateCondBr(cond, true_bb, false_bb); 191 if (false) { 192 // TODO: http://b/8511695 Restore branch weight metadata 193 branch_inst->setMetadata(::llvm::LLVMContext::MD_prof, mdb_.GetBranchWeights(expect)); 194 } 195 return branch_inst; 196 } 197 198 199 //-------------------------------------------------------------------------- 200 // Pointer Arithmetic Helper Function 201 //-------------------------------------------------------------------------- 202 getPtrEquivIntTy()203 ::llvm::IntegerType* getPtrEquivIntTy() { 204 return getInt32Ty(); 205 } 206 getSizeOfPtrEquivInt()207 size_t getSizeOfPtrEquivInt() { 208 return 4; 209 } 210 getSizeOfPtrEquivIntValue()211 ::llvm::ConstantInt* getSizeOfPtrEquivIntValue() { 212 return getPtrEquivInt(getSizeOfPtrEquivInt()); 213 } 214 getPtrEquivInt(int64_t i)215 ::llvm::ConstantInt* getPtrEquivInt(int64_t i) { 216 return ::llvm::ConstantInt::get(getPtrEquivIntTy(), i); 217 } 218 CreatePtrDisp(::llvm::Value * base,::llvm::Value * offset,::llvm::PointerType * ret_ty)219 ::llvm::Value* CreatePtrDisp(::llvm::Value* base, 220 ::llvm::Value* offset, 221 ::llvm::PointerType* ret_ty) { 222 ::llvm::Value* base_int = CreatePtrToInt(base, getPtrEquivIntTy()); 223 ::llvm::Value* result_int = CreateAdd(base_int, offset); 224 ::llvm::Value* result = CreateIntToPtr(result_int, ret_ty); 225 226 return result; 227 } 228 CreatePtrDisp(::llvm::Value * base,::llvm::Value * bs,::llvm::Value * count,::llvm::Value * offset,::llvm::PointerType * ret_ty)229 ::llvm::Value* CreatePtrDisp(::llvm::Value* base, 230 ::llvm::Value* bs, 231 ::llvm::Value* count, 232 ::llvm::Value* offset, 233 ::llvm::PointerType* ret_ty) { 234 ::llvm::Value* block_offset = CreateMul(bs, count); 235 ::llvm::Value* total_offset = CreateAdd(block_offset, offset); 236 237 return CreatePtrDisp(base, total_offset, ret_ty); 238 } 239 LoadFromObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Type * type,::llvm::MDNode * tbaa_info)240 ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr, 241 int64_t offset, 242 ::llvm::Type* type, 243 ::llvm::MDNode* tbaa_info) { 244 // Convert offset to ::llvm::value 245 ::llvm::Value* llvm_offset = getPtrEquivInt(offset); 246 // Calculate the value's address 247 ::llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo()); 248 // Load 249 return CreateLoad(value_addr, tbaa_info); 250 } 251 StoreToObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * new_value,::llvm::MDNode * tbaa_info)252 void StoreToObjectOffset(::llvm::Value* object_addr, 253 int64_t offset, 254 ::llvm::Value* new_value, 255 ::llvm::MDNode* tbaa_info) { 256 // Convert offset to ::llvm::value 257 ::llvm::Value* llvm_offset = getPtrEquivInt(offset); 258 // Calculate the value's address 259 ::llvm::Value* value_addr = CreatePtrDisp(object_addr, 260 llvm_offset, 261 new_value->getType()->getPointerTo()); 262 // Store 263 CreateStore(new_value, value_addr, tbaa_info); 264 } 265 CompareExchangeObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * cmp_value,::llvm::Value * new_value,::llvm::MDNode * tbaa_info)266 ::llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(::llvm::Value* object_addr, 267 int64_t offset, 268 ::llvm::Value* cmp_value, 269 ::llvm::Value* new_value, 270 ::llvm::MDNode* tbaa_info) { 271 // Convert offset to ::llvm::value 272 ::llvm::Value* llvm_offset = getPtrEquivInt(offset); 273 // Calculate the value's address 274 ::llvm::Value* value_addr = CreatePtrDisp(object_addr, 275 llvm_offset, 276 new_value->getType()->getPointerTo()); 277 // Atomic compare and exchange 278 return CreateAtomicCmpXchgInst(value_addr, cmp_value, new_value, tbaa_info); 279 } 280 281 282 //-------------------------------------------------------------------------- 283 // Runtime Helper Function 284 //-------------------------------------------------------------------------- 285 Runtime()286 RuntimeSupportBuilder& Runtime() { 287 return *runtime_support_; 288 } 289 290 // TODO: Deprecate GetRuntime(runtime_support::RuntimeId rt)291 ::llvm::Function* GetRuntime(runtime_support::RuntimeId rt) { 292 return runtime_support_->GetRuntimeSupportFunction(rt); 293 } 294 295 // TODO: Deprecate SetRuntimeSupport(RuntimeSupportBuilder * runtime_support)296 void SetRuntimeSupport(RuntimeSupportBuilder* runtime_support) { 297 // Can only set once. We can't do this on constructor, because RuntimeSupportBuilder needs 298 // IRBuilder. 299 if (runtime_support_ == NULL && runtime_support != NULL) { 300 runtime_support_ = runtime_support; 301 } 302 } 303 304 305 //-------------------------------------------------------------------------- 306 // Type Helper Function 307 //-------------------------------------------------------------------------- 308 getJType(char shorty_jty)309 ::llvm::Type* getJType(char shorty_jty) { 310 return getJType(GetJTypeFromShorty(shorty_jty)); 311 } 312 313 ::llvm::Type* getJType(JType jty); 314 getJVoidTy()315 ::llvm::Type* getJVoidTy() { 316 return getVoidTy(); 317 } 318 getJBooleanTy()319 ::llvm::IntegerType* getJBooleanTy() { 320 return getInt8Ty(); 321 } 322 getJByteTy()323 ::llvm::IntegerType* getJByteTy() { 324 return getInt8Ty(); 325 } 326 getJCharTy()327 ::llvm::IntegerType* getJCharTy() { 328 return getInt16Ty(); 329 } 330 getJShortTy()331 ::llvm::IntegerType* getJShortTy() { 332 return getInt16Ty(); 333 } 334 getJIntTy()335 ::llvm::IntegerType* getJIntTy() { 336 return getInt32Ty(); 337 } 338 getJLongTy()339 ::llvm::IntegerType* getJLongTy() { 340 return getInt64Ty(); 341 } 342 getJFloatTy()343 ::llvm::Type* getJFloatTy() { 344 return getFloatTy(); 345 } 346 getJDoubleTy()347 ::llvm::Type* getJDoubleTy() { 348 return getDoubleTy(); 349 } 350 getJObjectTy()351 ::llvm::PointerType* getJObjectTy() { 352 return java_object_type_; 353 } 354 getJMethodTy()355 ::llvm::PointerType* getJMethodTy() { 356 return java_method_type_; 357 } 358 getJThreadTy()359 ::llvm::PointerType* getJThreadTy() { 360 return java_thread_type_; 361 } 362 getArtFrameTy()363 ::llvm::Type* getArtFrameTy() { 364 return art_frame_type_; 365 } 366 getJEnvTy()367 ::llvm::PointerType* getJEnvTy() { 368 return jenv_type_; 369 } 370 getJValueTy()371 ::llvm::Type* getJValueTy() { 372 // NOTE: JValue is an union type, which may contains boolean, byte, char, 373 // short, int, long, float, double, Object. However, LLVM itself does 374 // not support union type, so we have to return a type with biggest size, 375 // then bitcast it before we use it. 376 return getJLongTy(); 377 } 378 379 ::llvm::StructType* getShadowFrameTy(uint32_t vreg_size); 380 381 382 //-------------------------------------------------------------------------- 383 // Constant Value Helper Function 384 //-------------------------------------------------------------------------- 385 getJBoolean(bool is_true)386 ::llvm::ConstantInt* getJBoolean(bool is_true) { 387 return (is_true) ? getTrue() : getFalse(); 388 } 389 getJByte(int8_t i)390 ::llvm::ConstantInt* getJByte(int8_t i) { 391 return ::llvm::ConstantInt::getSigned(getJByteTy(), i); 392 } 393 getJChar(int16_t i)394 ::llvm::ConstantInt* getJChar(int16_t i) { 395 return ::llvm::ConstantInt::getSigned(getJCharTy(), i); 396 } 397 getJShort(int16_t i)398 ::llvm::ConstantInt* getJShort(int16_t i) { 399 return ::llvm::ConstantInt::getSigned(getJShortTy(), i); 400 } 401 getJInt(int32_t i)402 ::llvm::ConstantInt* getJInt(int32_t i) { 403 return ::llvm::ConstantInt::getSigned(getJIntTy(), i); 404 } 405 getJLong(int64_t i)406 ::llvm::ConstantInt* getJLong(int64_t i) { 407 return ::llvm::ConstantInt::getSigned(getJLongTy(), i); 408 } 409 getJFloat(float f)410 ::llvm::Constant* getJFloat(float f) { 411 return ::llvm::ConstantFP::get(getJFloatTy(), f); 412 } 413 getJDouble(double d)414 ::llvm::Constant* getJDouble(double d) { 415 return ::llvm::ConstantFP::get(getJDoubleTy(), d); 416 } 417 getJNull()418 ::llvm::ConstantPointerNull* getJNull() { 419 return ::llvm::ConstantPointerNull::get(getJObjectTy()); 420 } 421 getJZero(char shorty_jty)422 ::llvm::Constant* getJZero(char shorty_jty) { 423 return getJZero(GetJTypeFromShorty(shorty_jty)); 424 } 425 getJZero(JType jty)426 ::llvm::Constant* getJZero(JType jty) { 427 switch (jty) { 428 case kVoid: 429 LOG(FATAL) << "Zero is not a value of void type"; 430 return NULL; 431 432 case kBoolean: 433 return getJBoolean(false); 434 435 case kByte: 436 return getJByte(0); 437 438 case kChar: 439 return getJChar(0); 440 441 case kShort: 442 return getJShort(0); 443 444 case kInt: 445 return getJInt(0); 446 447 case kLong: 448 return getJLong(0); 449 450 case kFloat: 451 return getJFloat(0.0f); 452 453 case kDouble: 454 return getJDouble(0.0); 455 456 case kObject: 457 return getJNull(); 458 459 default: 460 LOG(FATAL) << "Unknown java type: " << jty; 461 return NULL; 462 } 463 } 464 465 466 private: 467 ::llvm::Module* module_; 468 469 MDBuilder mdb_; 470 471 ::llvm::PointerType* java_object_type_; 472 ::llvm::PointerType* java_method_type_; 473 ::llvm::PointerType* java_thread_type_; 474 475 ::llvm::PointerType* jenv_type_; 476 477 ::llvm::StructType* art_frame_type_; 478 479 RuntimeSupportBuilder* runtime_support_; 480 481 IntrinsicHelper& intrinsic_helper_; 482 }; 483 484 485 } // namespace llvm 486 } // namespace art 487 488 #endif // ART_COMPILER_LLVM_IR_BUILDER_H_ 489