| 428 | } |
| 429 | |
| 430 | CodegenAnyValReadWriteInfo SlotRef::CreateCodegenAnyValReadWriteInfo( |
| 431 | LlvmCodeGen* codegen, LlvmBuilder* builder, llvm::Function* fn, |
| 432 | llvm::Value* eval_ptr, llvm::Value* row_ptr, llvm::BasicBlock* entry_block) { |
| 433 | llvm::IRBuilderBase::InsertPoint ip = builder->saveIP(); |
| 434 | |
| 435 | llvm::Value* tuple_offset = codegen->GetI32Constant(tuple_idx_); |
| 436 | llvm::Value* slot_offset = codegen->GetI32Constant(slot_offset_); |
| 437 | |
| 438 | llvm::LLVMContext& context = codegen->context(); |
| 439 | |
| 440 | // Create the necessary basic blocks. |
| 441 | if (entry_block == nullptr) { |
| 442 | entry_block = llvm::BasicBlock::Create(context, "entry", fn); |
| 443 | } |
| 444 | |
| 445 | llvm::BasicBlock* read_slot_block = llvm::BasicBlock::Create(context, "read_slot", fn); |
| 446 | |
| 447 | // We use this block to collect all code paths that lead to the result being null. It |
| 448 | // does nothing but branches unconditionally to 'produce_value_block' and the PHI nodes |
| 449 | // there can add this block as an incoming branch for the null case; it is simpler and |
| 450 | // more readable than having many predeccesor blocks for the null case in |
| 451 | // 'produce_value_block'. |
| 452 | llvm::BasicBlock* null_block = llvm::BasicBlock::Create(context, "null_block", fn); |
| 453 | |
| 454 | /// Start generating instructions. |
| 455 | //### Part 1: find the tuple address. |
| 456 | builder->SetInsertPoint(entry_block); |
| 457 | // Get the tuple offset addr from the row |
| 458 | llvm::Value* cast_row_ptr = builder->CreateBitCast( |
| 459 | row_ptr, codegen->ptr_ptr_type(), "cast_row_ptr"); |
| 460 | llvm::Value* tuple_ptr_addr = |
| 461 | builder->CreateInBoundsGEP(cast_row_ptr, tuple_offset, "tuple_ptr_addr"); |
| 462 | // Load the tuple* |
| 463 | llvm::Value* tuple_ptr = builder->CreateLoad(tuple_ptr_addr, "tuple_ptr"); |
| 464 | |
| 465 | //### Part 2: null checking |
| 466 | CodegenNullChecking(codegen, builder, fn, null_block, read_slot_block, tuple_ptr); |
| 467 | |
| 468 | //### Part 3: read non-null value. |
| 469 | CodegenAnyValReadWriteInfo res = CodegenReadSlot(codegen, builder, eval_ptr, |
| 470 | row_ptr, entry_block, null_block, read_slot_block, tuple_ptr, slot_offset); |
| 471 | |
| 472 | builder->restoreIP(ip); |
| 473 | return res; |
| 474 | } |
| 475 | |
| 476 | #define SLOT_REF_GET_FUNCTION(type_lit, type_val, type_c) \ |
| 477 | type_val SlotRef::Get##type_val##Interpreted( \ |
no test coverage detected