authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-31 15:50:38-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-31 15:50:38-05:00
log88a253c64dc148a6f09e4e872e3abbcd37fcc18a
tree09250f1da80d3f0afb82c38e76dec9dad3969403
parentb258fdb532a36f8ee9f091ac588a6189bad81acd

fix crash when passing void to var args function

closes #235

5 files changed, 43 insertions(+), 8 deletions(-)

src/all_types.hpp+1
...@@ -1262,6 +1262,7 @@ struct CodeGen {...@@ -1262,6 +1262,7 @@ struct CodeGen {
1262 LLVMValueRef err_name_table;1262 LLVMValueRef err_name_table;
12631263
1264 IrInstruction *invalid_instruction;1264 IrInstruction *invalid_instruction;
1265 ConstExprValue const_void_val;
1265};1266};
12661267
1267// TODO after merging IR branch, we can probably delete some of these fields1268// TODO after merging IR branch, we can probably delete some of these fields
src/codegen.cpp+3
...@@ -3738,6 +3738,9 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -3738,6 +3738,9 @@ static void init(CodeGen *g, Buf *source_path) {
37383738
3739 g->invalid_instruction = allocate<IrInstruction>(1);3739 g->invalid_instruction = allocate<IrInstruction>(1);
3740 g->invalid_instruction->value.type = g->builtin_types.entry_invalid;3740 g->invalid_instruction->value.type = g->builtin_types.entry_invalid;
3741
3742 g->const_void_val.special = ConstValSpecialStatic;
3743 g->const_void_val.type = g->builtin_types.entry_void;
3741}3744}
37423745
3743void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {3746void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
src/ir.cpp+27-8
...@@ -7397,7 +7397,7 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *...@@ -7397,7 +7397,7 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
7397 op2_array_end = op2_array_val->data.x_array.size - 1;7397 op2_array_end = op2_array_val->data.x_array.size - 1;
7398 } else {7398 } else {
7399 ir_add_error(ira, op2,7399 ir_add_error(ira, op2,
7400 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));7400 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
7401 // TODO if meta_type is type decl, add note pointing to type decl declaration7401 // TODO if meta_type is type decl, add note pointing to type decl declaration
7402 return ira->codegen->builtin_types.entry_invalid;7402 return ira->codegen->builtin_types.entry_invalid;
7403 }7403 }
...@@ -8511,6 +8511,23 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct...@@ -8511,6 +8511,23 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
8511 return ir_analyze_var_ptr(ira, &var_ptr_instruction->base, var, var_ptr_instruction->is_const, false);8511 return ir_analyze_var_ptr(ira, &var_ptr_instruction->base, var, var_ptr_instruction->is_const, false);
8512}8512}
85138513
8514static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t index) {
8515 size_t next_var_i = 0;
8516 FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info;
8517 for (size_t param_i = 0; param_i < index; param_i += 1) {
8518 FnGenParamInfo *info = &gen_param_info[param_i];
8519 if (info->gen_index == SIZE_MAX)
8520 continue;
8521
8522 next_var_i += 1;
8523 }
8524 FnGenParamInfo *info = &gen_param_info[index];
8525 if (info->gen_index == SIZE_MAX)
8526 return nullptr;
8527
8528 return fn_entry->variable_list.at(next_var_i);
8529}
8530
8514static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {8531static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
8515 IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other;8532 IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other;
8516 if (array_ptr->value.type->id == TypeTableEntryIdInvalid)8533 if (array_ptr->value.type->id == TypeTableEntryIdInvalid)
...@@ -8560,10 +8577,15 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -8560,10 +8577,15 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
8560 size_t abs_index = start + index;8577 size_t abs_index = start + index;
8561 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);8578 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
8562 assert(fn_entry);8579 assert(fn_entry);
8563 VariableTableEntry *var = fn_entry->variable_list.at(abs_index);8580 VariableTableEntry *var = get_fn_var_by_index(fn_entry, abs_index);
8564 bool depends_on_compile_var = array_ptr->value.depends_on_compile_var ||8581 bool depends_on_compile_var = array_ptr->value.depends_on_compile_var ||
8565 elem_index->value.depends_on_compile_var;8582 elem_index->value.depends_on_compile_var;
8566 return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var, true, depends_on_compile_var);8583 if (var) {
8584 return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var, true, depends_on_compile_var);
8585 } else {
8586 return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,
8587 ira->codegen->builtin_types.entry_void, depends_on_compile_var, ConstPtrSpecialNone, true);
8588 }
8567 } else {8589 } else {
8568 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,8590 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
8569 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));8591 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
...@@ -10445,16 +10467,13 @@ static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstru...@@ -10445,16 +10467,13 @@ static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstru
10445 if (type_entry->id == TypeTableEntryIdInvalid)10467 if (type_entry->id == TypeTableEntryIdInvalid)
10446 return ira->codegen->builtin_types.entry_invalid;10468 return ira->codegen->builtin_types.entry_invalid;
1044710469
10448 TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
10449 if (!type_entry->cached_const_name_val) {10470 if (!type_entry->cached_const_name_val) {
10450 ConstExprValue *array_val = create_const_str_lit(ira->codegen, &type_entry->name);10471 type_entry->cached_const_name_val = create_const_str_lit(ira->codegen, &type_entry->name);
10451 type_entry->cached_const_name_val = create_const_slice(ira->codegen,
10452 array_val, 0, buf_len(&type_entry->name), true);
10453 }10472 }
10454 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base,10473 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base,
10455 type_value->value.depends_on_compile_var);10474 type_value->value.depends_on_compile_var);
10456 *out_val = *type_entry->cached_const_name_val;10475 *out_val = *type_entry->cached_const_name_val;
10457 return str_type;10476 return out_val->type;
10458}10477}
1045910478
10460static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {10479static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
std/io.zig+2
...@@ -165,6 +165,8 @@ pub const OutStream = struct {...@@ -165,6 +165,8 @@ pub const OutStream = struct {
165 } else if (@canImplicitCast([]const u8, value)) {165 } else if (@canImplicitCast([]const u8, value)) {
166 const casted_value = ([]const u8)(value);166 const casted_value = ([]const u8)(value);
167 return self.write(casted_value);167 return self.write(casted_value);
168 } else if (T == void) {
169 return self.write("void");
168 } else {170 } else {
169 @compileError("Unable to print type '" ++ @typeName(T) ++ "'");171 @compileError("Unable to print type '" ++ @typeName(T) ++ "'");
170 }172 }
test/cases/var_args.zig+10
...@@ -15,3 +15,13 @@ fn testAddArbitraryArgs() {...@@ -15,3 +15,13 @@ fn testAddArbitraryArgs() {
15 assert(add(i32(1234)) == 1234);15 assert(add(i32(1234)) == 1234);
16 assert(add() == 0);16 assert(add() == 0);
17}17}
18
19fn readFirstVarArg(args: ...) {
20 const value = args[0];
21}
22
23fn sendVoidArgToVarArgs() {
24 @setFnTest(this);
25
26 readFirstVarArg({});
27}