| 504 | } |
| 505 | |
| 506 | Status Tuple::CodegenCopyStrings( |
| 507 | LlvmCodeGen* codegen, const TupleDescriptor& desc, llvm::Function** copy_strings_fn) { |
| 508 | llvm::PointerType* opaque_tuple_type = codegen->GetStructPtrType<Tuple>(); |
| 509 | llvm::PointerType* runtime_state_type = codegen->GetStructPtrType<RuntimeState>(); |
| 510 | llvm::StructType* slot_offsets_type = codegen->GetStructType<SlotOffsets>(); |
| 511 | llvm::PointerType* pool_type = codegen->GetStructPtrType<MemPool>(); |
| 512 | llvm::PointerType* status_type = codegen->GetStructPtrType<Status>(); |
| 513 | LlvmCodeGen::FnPrototype prototype( |
| 514 | codegen, "CopyStringsWrapper", codegen->bool_type()); |
| 515 | prototype.AddArgument("opaque_tuple", opaque_tuple_type); |
| 516 | prototype.AddArgument("err_ctx", codegen->ptr_type()); |
| 517 | prototype.AddArgument("state", runtime_state_type); |
| 518 | prototype.AddArgument("slot_offsets", codegen->GetPtrType(slot_offsets_type)); |
| 519 | prototype.AddArgument("num_string_slots", codegen->i32_type()); |
| 520 | prototype.AddArgument("pool", pool_type); |
| 521 | prototype.AddArgument("status", status_type); |
| 522 | |
| 523 | LlvmBuilder builder(codegen->context()); |
| 524 | llvm::Value* args[7]; |
| 525 | *copy_strings_fn = prototype.GeneratePrototype(&builder, args); |
| 526 | llvm::Value* opaque_tuple_arg = args[0]; |
| 527 | llvm::Value* err_ctx_arg = args[1]; |
| 528 | llvm::Value* state_arg = args[2]; |
| 529 | // slot_offsets and num_string_slots are replaced with constants so args are unused. |
| 530 | llvm::Value* pool_arg = args[5]; |
| 531 | llvm::Value* status_arg = args[6]; |
| 532 | |
| 533 | llvm::Function* cross_compiled_fn = |
| 534 | codegen->GetFunction(IRFunction::TUPLE_COPY_STRINGS, false); |
| 535 | DCHECK(cross_compiled_fn != nullptr); |
| 536 | |
| 537 | // Convert the offsets of the string slots into a constant IR array 'slot_offsets'. |
| 538 | vector<llvm::Constant*> slot_offset_ir_constants; |
| 539 | for (SlotDescriptor* slot_desc : desc.string_slots()) { |
| 540 | SlotOffsets offsets = {slot_desc->null_indicator_offset(), slot_desc->tuple_offset()}; |
| 541 | slot_offset_ir_constants.push_back(offsets.ToIR(codegen)); |
| 542 | } |
| 543 | llvm::Constant* constant_slot_offsets = codegen->ConstantsToGVArrayPtr( |
| 544 | slot_offsets_type, slot_offset_ir_constants, "slot_offsets"); |
| 545 | llvm::Constant* num_string_slots = codegen->GetI32Constant(desc.string_slots().size()); |
| 546 | // Get SlotOffsets* pointer to the first element of the constant array. |
| 547 | llvm::Value* constant_slot_offsets_first_element_ptr = |
| 548 | builder.CreateConstGEP2_64(constant_slot_offsets, 0, 0); |
| 549 | |
| 550 | llvm::Value* result_val = builder.CreateCall(cross_compiled_fn, |
| 551 | {opaque_tuple_arg, err_ctx_arg, state_arg, constant_slot_offsets_first_element_ptr, |
| 552 | num_string_slots, pool_arg, status_arg}); |
| 553 | builder.CreateRet(result_val); |
| 554 | |
| 555 | *copy_strings_fn = codegen->FinalizeFunction(*copy_strings_fn); |
| 556 | if (*copy_strings_fn == nullptr) { |
| 557 | return Status("Tuple::CodegenCopyStrings(): failed to finalize function"); |
| 558 | } |
| 559 | return Status::OK(); |
| 560 | } |
| 561 | |
| 562 | llvm::Constant* SlotOffsets::ToIR(LlvmCodeGen* codegen) const { |
| 563 | return llvm::ConstantStruct::get( |
nothing calls this directly
no test coverage detected