Codegen for a function to parse one slot. The IR for a int slot looks like: define i1 @WriteSlot(<{ i32, i8 }>* %tuple_arg, i8* %data, i32 %len) #38 { entry: %parse_result = alloca i32 %0 = call i1 @IrIsNullString(i8* %data, i32 %len) br i1 %0, label %set_null, label %check_zero set_null: ; preds = %check_zero, %entry %1 = bitcast <{ i32, i8 }>* %tuple_arg
| 108 | // TODO: convert this function to use cross-compilation + constant substitution in whole |
| 109 | // or part. It is currently too complex and doesn't implement the full functionality. |
| 110 | Status TextConverter::CodegenWriteSlot(LlvmCodeGen* codegen, TupleDescriptor* tuple_desc, |
| 111 | SlotDescriptor* slot_desc, llvm::Function** fn, const char* null_col_val, int len, |
| 112 | bool check_null, bool strict_mode) { |
| 113 | DCHECK(fn != nullptr); |
| 114 | DCHECK(SupportsCodegenWriteSlot(slot_desc->type())); |
| 115 | |
| 116 | // Codegen is_null_string |
| 117 | bool is_default_null = (len == 2 && null_col_val[0] == '\\' && null_col_val[1] == 'N'); |
| 118 | llvm::Function* is_null_string_fn; |
| 119 | if (is_default_null) { |
| 120 | is_null_string_fn = codegen->GetFunction(IRFunction::IS_NULL_STRING, false); |
| 121 | } else { |
| 122 | is_null_string_fn = codegen->GetFunction(IRFunction::GENERIC_IS_NULL_STRING, false); |
| 123 | } |
| 124 | |
| 125 | DCHECK(is_null_string_fn != NULL); |
| 126 | |
| 127 | llvm::StructType* tuple_type = tuple_desc->GetLlvmStruct(codegen); |
| 128 | if (tuple_type == NULL) { |
| 129 | return Status("TextConverter::CodegenWriteSlot(): Failed to generate " |
| 130 | "tuple type"); |
| 131 | } |
| 132 | llvm::PointerType* tuple_ptr_type = tuple_type->getPointerTo(); |
| 133 | |
| 134 | LlvmCodeGen::FnPrototype prototype( |
| 135 | codegen, "WriteSlot", codegen->bool_type()); |
| 136 | prototype.AddArgument(LlvmCodeGen::NamedVariable("tuple_arg", tuple_ptr_type)); |
| 137 | prototype.AddArgument(LlvmCodeGen::NamedVariable("data", codegen->ptr_type())); |
| 138 | prototype.AddArgument(LlvmCodeGen::NamedVariable("len", codegen->i32_type())); |
| 139 | |
| 140 | LlvmBuilder builder(codegen->context()); |
| 141 | llvm::Value* args[3]; |
| 142 | *fn = prototype.GeneratePrototype(&builder, &args[0]); |
| 143 | |
| 144 | llvm::BasicBlock *set_null_block, *parse_slot_block, *check_zero_block = NULL; |
| 145 | codegen->CreateIfElseBlocks(*fn, "set_null", "parse_slot", |
| 146 | &set_null_block, &parse_slot_block); |
| 147 | |
| 148 | if (!slot_desc->type().IsVarLenStringType()) { |
| 149 | check_zero_block = llvm::BasicBlock::Create(codegen->context(), "check_zero", *fn); |
| 150 | } |
| 151 | |
| 152 | // Check if the data matches the configured NULL string. |
| 153 | llvm::Value* is_null; |
| 154 | if (check_null) { |
| 155 | if (is_default_null) { |
| 156 | is_null = builder.CreateCall( |
| 157 | is_null_string_fn, llvm::ArrayRef<llvm::Value*>({args[1], args[2]})); |
| 158 | } else { |
| 159 | llvm::Value* const null_col_ir_str = |
| 160 | codegen->GetStringConstant(&builder, null_col_val, len); |
| 161 | is_null = builder.CreateCall(is_null_string_fn, |
| 162 | llvm::ArrayRef<llvm::Value*>( |
| 163 | {args[1], args[2], null_col_ir_str, codegen->GetI32Constant(len)})); |
| 164 | } |
| 165 | } else { |
| 166 | // Constant FALSE as branch condition. We rely on later optimization passes |
| 167 | // to remove the branch and THEN block. |
nothing calls this directly
no test coverage detected