authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-08 01:52:57-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-08 01:52:57-05:00
log7d0fb281fee16d9c99f61c5bce090018228ae6df
tree4fe6b845e03cb6b19e399283f5501d444cf2185a
parenta148096e6a2d28e6248eed9b5a4ad40482b74149

IR: a bunch of fixes and some additions

* add errorName builtin function * add assertion for generated memcopy being on correct types * respect handle_is_ptr for constant values * fix return codegen to respect sret semantics * remove ArrayLen IR instruction; we already have StructFieldPtr with "len" field * fix gen_const_val for pointers inside aggregates

6 files changed, 203 insertions(+), 95 deletions(-)

src/all_types.hpp+9-1
...@@ -128,7 +128,8 @@ struct ConstExprValue {...@@ -128,7 +128,8 @@ struct ConstExprValue {
128 ConstBoundFnValue x_bound_fn;128 ConstBoundFnValue x_bound_fn;
129 TypeTableEntry *x_type;129 TypeTableEntry *x_type;
130 ConstExprValue *x_maybe;130 ConstExprValue *x_maybe;
131 ConstErrValue x_err;131 ConstErrValue x_err_union;
132 ErrorTableEntry *x_pure_err;
132 ConstEnumValue x_enum;133 ConstEnumValue x_enum;
133 ConstStructValue x_struct;134 ConstStructValue x_struct;
134 ConstArrayValue x_array;135 ConstArrayValue x_array;
...@@ -1395,6 +1396,7 @@ enum IrInstructionId {...@@ -1395,6 +1396,7 @@ enum IrInstructionId {
1395 IrInstructionIdMinValue,1396 IrInstructionIdMinValue,
1396 IrInstructionIdMaxValue,1397 IrInstructionIdMaxValue,
1397 IrInstructionIdCompileErr,1398 IrInstructionIdCompileErr,
1399 IrInstructionIdErrName,
1398};1400};
13991401
1400struct IrInstruction {1402struct IrInstruction {
...@@ -1811,6 +1813,12 @@ struct IrInstructionCompileErr {...@@ -1811,6 +1813,12 @@ struct IrInstructionCompileErr {
1811 IrInstruction *msg;1813 IrInstruction *msg;
1812};1814};
18131815
1816struct IrInstructionErrName {
1817 IrInstruction base;
1818
1819 IrInstruction *value;
1820};
1821
1814enum LValPurpose {1822enum LValPurpose {
1815 LValPurposeNone,1823 LValPurposeNone,
1816 LValPurposeAssign,1824 LValPurposeAssign,
src/codegen.cpp+61-10
...@@ -615,6 +615,9 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef...@@ -615,6 +615,9 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef
615{615{
616 assert(handle_is_ptr(type_entry));616 assert(handle_is_ptr(type_entry));
617617
618 assert(LLVMGetTypeKind(LLVMTypeOf(src)) == LLVMPointerTypeKind);
619 assert(LLVMGetTypeKind(LLVMTypeOf(dest)) == LLVMPointerTypeKind);
620
618 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);621 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
619622
620 LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");623 LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");
...@@ -669,7 +672,12 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -669,7 +672,12 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
669 assert(instruction->static_value.special != ConstValSpecialRuntime);672 assert(instruction->static_value.special != ConstValSpecialRuntime);
670 assert(instruction->type_entry);673 assert(instruction->type_entry);
671 render_const_val(g, instruction->type_entry, &instruction->static_value);674 render_const_val(g, instruction->type_entry, &instruction->static_value);
672 instruction->llvm_value = instruction->static_value.llvm_value;675 if (handle_is_ptr(instruction->type_entry)) {
676 render_const_val_global(g, instruction->type_entry, &instruction->static_value);
677 instruction->llvm_value = instruction->static_value.llvm_global;
678 } else {
679 instruction->llvm_value = instruction->static_value.llvm_value;
680 }
673 assert(instruction->llvm_value);681 assert(instruction->llvm_value);
674 }682 }
675 if (instruction->static_value.special != ConstValSpecialRuntime) {683 if (instruction->static_value.special != ConstValSpecialRuntime) {
...@@ -681,7 +689,22 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -681,7 +689,22 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
681}689}
682690
683static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {691static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
684 LLVMBuildRet(g->builder, ir_llvm_value(g, return_instruction->value));692 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
693 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
694 bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;
695 if (handle_is_ptr(return_type)) {
696 if (is_extern) {
697 LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
698 LLVMBuildRet(g->builder, by_val_value);
699 } else {
700 assert(g->cur_ret_ptr);
701 gen_assign_raw(g, return_instruction->base.source_node, g->cur_ret_ptr, value,
702 return_type, return_instruction->value->type_entry);
703 LLVMBuildRetVoid(g->builder);
704 }
705 } else {
706 LLVMBuildRet(g->builder, value);
707 }
685 return nullptr;708 return nullptr;
686}709}
687710
...@@ -1790,6 +1813,28 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1790,6 +1813,28 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru
1790 }1813 }
1791}1814}
17921815
1816static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrInstructionErrName *instruction) {
1817 assert(g->generate_error_name_table);
1818
1819 if (g->error_decls.length == 1) {
1820 LLVMBuildUnreachable(g->builder);
1821 return nullptr;
1822 }
1823
1824 LLVMValueRef err_val = ir_llvm_value(g, instruction->value);
1825 if (ir_want_debug_safety(g, &instruction->base)) {
1826 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
1827 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
1828 add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
1829 }
1830
1831 LLVMValueRef indices[] = {
1832 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
1833 err_val,
1834 };
1835 return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, "");
1836}
1837
1793static void set_debug_location(CodeGen *g, IrInstruction *instruction) {1838static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
1794 AstNode *source_node = instruction->source_node;1839 AstNode *source_node = instruction->source_node;
1795 Scope *scope = instruction->scope;1840 Scope *scope = instruction->scope;
...@@ -1824,6 +1869,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1824,6 +1869,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1824 case IrInstructionIdMinValue:1869 case IrInstructionIdMinValue:
1825 case IrInstructionIdMaxValue:1870 case IrInstructionIdMaxValue:
1826 case IrInstructionIdCompileErr:1871 case IrInstructionIdCompileErr:
1872 case IrInstructionIdArrayLen:
1827 zig_unreachable();1873 zig_unreachable();
1828 case IrInstructionIdReturn:1874 case IrInstructionIdReturn:
1829 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);1875 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -1871,11 +1917,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1871,11 +1917,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1871 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);1917 return ir_render_phi(g, executable, (IrInstructionPhi *)instruction);
1872 case IrInstructionIdRef:1918 case IrInstructionIdRef:
1873 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);1919 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
1920 case IrInstructionIdErrName:
1921 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
1874 case IrInstructionIdSwitchVar:1922 case IrInstructionIdSwitchVar:
1875 case IrInstructionIdContainerInitList:1923 case IrInstructionIdContainerInitList:
1876 case IrInstructionIdStructInit:1924 case IrInstructionIdStructInit:
1877 case IrInstructionIdEnumTag:1925 case IrInstructionIdEnumTag:
1878 case IrInstructionIdArrayLen:
1879 zig_panic("TODO render more IR instructions to LLVM");1926 zig_panic("TODO render more IR instructions to LLVM");
1880 }1927 }
1881 zig_unreachable();1928 zig_unreachable();
...@@ -1919,9 +1966,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -1919,9 +1966,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
1919 case TypeTableEntryIdInt:1966 case TypeTableEntryIdInt:
1920 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);1967 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
1921 case TypeTableEntryIdPureError:1968 case TypeTableEntryIdPureError:
1922 assert(const_val->data.x_err.err);1969 assert(const_val->data.x_pure_err);
1923 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,1970 return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
1924 const_val->data.x_err.err->value, false);1971 const_val->data.x_pure_err->value, false);
1925 case TypeTableEntryIdFloat:1972 case TypeTableEntryIdFloat:
1926 if (const_val->data.x_bignum.kind == BigNumKindFloat) {1973 if (const_val->data.x_bignum.kind == BigNumKindFloat) {
1927 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);1974 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
...@@ -2045,7 +2092,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2045,7 +2092,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2045 if (index == SIZE_MAX) {2092 if (index == SIZE_MAX) {
2046 render_const_val(g, child_type, const_val->data.x_ptr.base_ptr);2093 render_const_val(g, child_type, const_val->data.x_ptr.base_ptr);
2047 render_const_val_global(g, child_type, const_val->data.x_ptr.base_ptr);2094 render_const_val_global(g, child_type, const_val->data.x_ptr.base_ptr);
2048 return const_val->data.x_ptr.base_ptr->llvm_global;2095 const_val->llvm_value = const_val->data.x_ptr.base_ptr->llvm_global;
2096 render_const_val_global(g, type_entry, const_val);
2097 return const_val->llvm_value;
2049 } else {2098 } else {
2050 ConstExprValue *array_const_val = const_val->data.x_ptr.base_ptr;2099 ConstExprValue *array_const_val = const_val->data.x_ptr.base_ptr;
2051 TypeTableEntry *array_type = get_array_type(g, child_type,2100 TypeTableEntry *array_type = get_array_type(g, child_type,
...@@ -2058,6 +2107,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2058,6 +2107,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2058 LLVMConstInt(usize->type_ref, index, false),2107 LLVMConstInt(usize->type_ref, index, false),
2059 };2108 };
2060 LLVMValueRef ptr_val = LLVMConstInBoundsGEP(array_const_val->llvm_global, indices, 2);2109 LLVMValueRef ptr_val = LLVMConstInBoundsGEP(array_const_val->llvm_global, indices, 2);
2110 const_val->llvm_value = ptr_val;
2111 render_const_val_global(g, type_entry, const_val);
2061 return ptr_val;2112 return ptr_val;
2062 }2113 }
2063 }2114 }
...@@ -2065,17 +2116,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2065,17 +2116,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2065 {2116 {
2066 TypeTableEntry *child_type = type_entry->data.error.child_type;2117 TypeTableEntry *child_type = type_entry->data.error.child_type;
2067 if (!type_has_bits(child_type)) {2118 if (!type_has_bits(child_type)) {
2068 uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0;2119 uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
2069 return LLVMConstInt(g->err_tag_type->type_ref, value, false);2120 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
2070 } else {2121 } else {
2071 LLVMValueRef err_tag_value;2122 LLVMValueRef err_tag_value;
2072 LLVMValueRef err_payload_value;2123 LLVMValueRef err_payload_value;
2073 if (const_val->data.x_err.err) {2124 if (const_val->data.x_err_union.err) {
2074 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err.err->value, false);2125 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
2075 err_payload_value = LLVMConstNull(child_type->type_ref);2126 err_payload_value = LLVMConstNull(child_type->type_ref);
2076 } else {2127 } else {
2077 err_tag_value = LLVMConstNull(g->err_tag_type->type_ref);2128 err_tag_value = LLVMConstNull(g->err_tag_type->type_ref);
2078 err_payload_value = gen_const_val(g, child_type, const_val->data.x_err.payload);2129 err_payload_value = gen_const_val(g, child_type, const_val->data.x_err_union.payload);
2079 }2130 }
2080 LLVMValueRef fields[] = {2131 LLVMValueRef fields[] = {
2081 err_tag_value,2132 err_tag_value,
src/eval.cpp+12-5
...@@ -30,7 +30,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty...@@ -30,7 +30,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty
30 case TypeTableEntryIdVoid:30 case TypeTableEntryIdVoid:
31 return true;31 return true;
32 case TypeTableEntryIdPureError:32 case TypeTableEntryIdPureError:
33 return a->data.x_err.err == b->data.x_err.err;33 return a->data.x_pure_err == b->data.x_pure_err;
34 case TypeTableEntryIdFn:34 case TypeTableEntryIdFn:
35 return a->data.x_fn == b->data.x_fn;35 return a->data.x_fn == b->data.x_fn;
36 case TypeTableEntryIdBool:36 case TypeTableEntryIdBool:
...@@ -351,17 +351,24 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -351,17 +351,24 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
351 const_val->special = ConstValSpecialStatic;351 const_val->special = ConstValSpecialStatic;
352 break;352 break;
353 case CastOpErrorWrap:353 case CastOpErrorWrap:
354 const_val->data.x_err.err = nullptr;354 const_val->data.x_err_union.err = nullptr;
355 const_val->data.x_err.payload = other_val;355 const_val->data.x_err_union.payload = other_val;
356 const_val->special = ConstValSpecialStatic;356 const_val->special = ConstValSpecialStatic;
357 break;357 break;
358 case CastOpPureErrorWrap:358 case CastOpPureErrorWrap:
359 const_val->data.x_err.err = other_val->data.x_err.err;359 const_val->data.x_err_union.err = other_val->data.x_pure_err;
360 const_val->special = ConstValSpecialStatic;360 const_val->special = ConstValSpecialStatic;
361 break;361 break;
362 case CastOpErrToInt:362 case CastOpErrToInt:
363 {363 {
364 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;364 uint64_t value;
365 if (other_type->id == TypeTableEntryIdErrorUnion) {
366 value = other_val->data.x_err_union.err ? other_val->data.x_err_union.err->value : 0;
367 } else if (other_type->id == TypeTableEntryIdPureError) {
368 value = other_val->data.x_pure_err->value;
369 } else {
370 zig_unreachable();
371 }
365 bignum_init_unsigned(&const_val->data.x_bignum, value);372 bignum_init_unsigned(&const_val->data.x_bignum, value);
366 const_val->special = ConstValSpecialStatic;373 const_val->special = ConstValSpecialStatic;
367 break;374 break;
src/ir.cpp+91-79
...@@ -318,6 +318,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {...@@ -318,6 +318,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) {
318 return IrInstructionIdCompileErr;318 return IrInstructionIdCompileErr;
319}319}
320320
321static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) {
322 return IrInstructionIdErrName;
323}
324
321template<typename T>325template<typename T>
322static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {326static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
323 T *special_instruction = allocate<T>(1);327 T *special_instruction = allocate<T>(1);
...@@ -508,8 +512,8 @@ static IrInstruction *ir_build_const_bound_fn(IrBuilder *irb, Scope *scope, AstN...@@ -508,8 +512,8 @@ static IrInstruction *ir_build_const_bound_fn(IrBuilder *irb, Scope *scope, AstN
508 return &const_instruction->base;512 return &const_instruction->base;
509}513}
510514
511static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {515static IrInstruction *ir_create_const_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {
512 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);516 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, scope, source_node);
513 TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8;517 TypeTableEntry *u8_type = irb->codegen->builtin_types.entry_u8;
514 TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str));518 TypeTableEntry *type_entry = get_array_type(irb->codegen, u8_type, buf_len(str));
515 const_instruction->base.type_entry = type_entry;519 const_instruction->base.type_entry = type_entry;
...@@ -526,6 +530,11 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo...@@ -526,6 +530,11 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo
526530
527 return &const_instruction->base;531 return &const_instruction->base;
528}532}
533static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {
534 IrInstruction *instruction = ir_create_const_str_lit(irb, scope, source_node, str);
535 ir_instruction_append(irb->current_basic_block, instruction);
536 return instruction;
537}
529538
530static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {539static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {
531 // first we build the underlying array540 // first we build the underlying array
...@@ -1229,15 +1238,6 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode *...@@ -1229,15 +1238,6 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode *
1229 return &instruction->base;1238 return &instruction->base;
1230}1239}
12311240
1232static IrInstruction *ir_build_array_len_from(IrBuilder *irb, IrInstruction *old_instruction,
1233 IrInstruction *array_value)
1234{
1235 IrInstruction *new_instruction = ir_build_array_len(irb, old_instruction->scope,
1236 old_instruction->source_node, array_value);
1237 ir_link_new_instruction(new_instruction, old_instruction);
1238 return new_instruction;
1239}
1240
1241static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1241static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1242 IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node);1242 IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node);
1243 instruction->value = value;1243 instruction->value = value;
...@@ -1280,6 +1280,22 @@ static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode...@@ -1280,6 +1280,22 @@ static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode
1280 return &instruction->base;1280 return &instruction->base;
1281}1281}
12821282
1283static IrInstruction *ir_build_err_name(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1284 IrInstructionErrName *instruction = ir_build_instruction<IrInstructionErrName>(irb, scope, source_node);
1285 instruction->value = value;
1286
1287 ir_ref_instruction(value);
1288
1289 return &instruction->base;
1290}
1291
1292static IrInstruction *ir_build_err_name_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
1293 IrInstruction *new_instruction = ir_build_err_name(irb, old_instruction->scope,
1294 old_instruction->source_node, value);
1295 ir_link_new_instruction(new_instruction, old_instruction);
1296 return new_instruction;
1297}
1298
12831299
1284static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,1300static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
1285 bool gen_error_defers, bool gen_maybe_defers)1301 bool gen_error_defers, bool gen_maybe_defers)
...@@ -1946,6 +1962,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -1946,6 +1962,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
19461962
1947 return ir_build_compile_err(irb, scope, node, arg0_value);1963 return ir_build_compile_err(irb, scope, node, arg0_value);
1948 }1964 }
1965 case BuiltinFnIdErrName:
1966 {
1967 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1968 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
1969 if (arg0_value == irb->codegen->invalid_instruction)
1970 return arg0_value;
1971
1972 return ir_build_err_name(irb, scope, node, arg0_value);
1973 }
1949 case BuiltinFnIdMemcpy:1974 case BuiltinFnIdMemcpy:
1950 case BuiltinFnIdMemset:1975 case BuiltinFnIdMemset:
1951 case BuiltinFnIdAlignof:1976 case BuiltinFnIdAlignof:
...@@ -1958,7 +1983,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -1958,7 +1983,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
1958 case BuiltinFnIdCDefine:1983 case BuiltinFnIdCDefine:
1959 case BuiltinFnIdCUndef:1984 case BuiltinFnIdCUndef:
1960 case BuiltinFnIdCImport:1985 case BuiltinFnIdCImport:
1961 case BuiltinFnIdErrName:
1962 case BuiltinFnIdBreakpoint:1986 case BuiltinFnIdBreakpoint:
1963 case BuiltinFnIdReturnAddress:1987 case BuiltinFnIdReturnAddress:
1964 case BuiltinFnIdFrameAddress:1988 case BuiltinFnIdFrameAddress:
...@@ -2834,6 +2858,11 @@ static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode...@@ -2834,6 +2858,11 @@ static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode
2834 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_type);2858 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_type);
2835}2859}
28362860
2861static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {
2862 assert(node->type == NodeTypeErrorType);
2863 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_pure_error);
2864}
2865
2837static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) {2866static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
2838 assert(node->type == NodeTypeDefer);2867 assert(node->type == NodeTypeDefer);
28392868
...@@ -2903,6 +2932,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -2903,6 +2932,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
2903 return ir_lval_wrap(irb, scope, ir_gen_goto(irb, scope, node), lval);2932 return ir_lval_wrap(irb, scope, ir_gen_goto(irb, scope, node), lval);
2904 case NodeTypeTypeLiteral:2933 case NodeTypeTypeLiteral:
2905 return ir_lval_wrap(irb, scope, ir_gen_type_literal(irb, scope, node), lval);2934 return ir_lval_wrap(irb, scope, ir_gen_type_literal(irb, scope, node), lval);
2935 case NodeTypeErrorType:
2936 return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval);
2906 case NodeTypeBreak:2937 case NodeTypeBreak:
2907 return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval);2938 return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval);
2908 case NodeTypeContinue:2939 case NodeTypeContinue:
...@@ -2913,7 +2944,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -2913,7 +2944,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
2913 case NodeTypeSliceExpr:2944 case NodeTypeSliceExpr:
2914 case NodeTypeCharLiteral:2945 case NodeTypeCharLiteral:
2915 case NodeTypeZeroesLiteral:2946 case NodeTypeZeroesLiteral:
2916 case NodeTypeErrorType:
2917 case NodeTypeVarLiteral:2947 case NodeTypeVarLiteral:
2918 case NodeTypeRoot:2948 case NodeTypeRoot:
2919 case NodeTypeFnProto:2949 case NodeTypeFnProto:
...@@ -5564,7 +5594,20 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -5564,7 +5594,20 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
5564 return ira->codegen->builtin_types.entry_invalid;5594 return ira->codegen->builtin_types.entry_invalid;
5565 }5595 }
5566 } else if (child_type->id == TypeTableEntryIdPureError) {5596 } else if (child_type->id == TypeTableEntryIdPureError) {
5567 zig_panic("TODO error type field");5597 auto err_table_entry = ira->codegen->error_table.maybe_get(field_name);
5598 if (err_table_entry) {
5599 ConstExprValue *const_val = allocate<ConstExprValue>(1);
5600 const_val->special = ConstValSpecialStatic;
5601 const_val->data.x_pure_err = err_table_entry->value;
5602
5603 bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var;
5604 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val,
5605 child_type, depends_on_compile_var, ConstPtrSpecialNone);
5606 }
5607
5608 ir_add_error(ira, &field_ptr_instruction->base,
5609 buf_sprintf("use of undeclared error value '%s'", buf_ptr(field_name)));
5610 return ira->codegen->builtin_types.entry_invalid;
5568 } else if (child_type->id == TypeTableEntryIdInt) {5611 } else if (child_type->id == TypeTableEntryIdInt) {
5569 zig_panic("TODO integer type field");5612 zig_panic("TODO integer type field");
5570 } else {5613 } else {
...@@ -6525,7 +6568,12 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,...@@ -6525,7 +6568,12 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
6525 len_val->data.x_bignum.data.x_uint, depends_on_compile_var);6568 len_val->data.x_bignum.data.x_uint, depends_on_compile_var);
6526 }6569 }
6527 }6570 }
6528 ir_build_array_len_from(&ira->new_irb, &array_len_instruction->base, array_value);6571 TypeStructField *field = find_struct_type_field(canon_type, buf_create_from_str("len"));
6572 assert(field);
6573 IrInstruction *len_ptr = ir_build_struct_field_ptr(&ira->new_irb, array_len_instruction->base.scope,
6574 array_len_instruction->base.source_node, array_value, field);
6575 len_ptr->type_entry = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_usize, true);
6576 ir_build_load_ptr_from(&ira->new_irb, &array_len_instruction->base, len_ptr);
6529 return ira->codegen->builtin_types.entry_usize;6577 return ira->codegen->builtin_types.entry_usize;
6530 } else {6578 } else {
6531 add_node_error(ira->codegen, array_len_instruction->base.source_node,6579 add_node_error(ira->codegen, array_len_instruction->base.source_node,
...@@ -6814,6 +6862,31 @@ static TypeTableEntry *ir_analyze_instruction_compile_err(IrAnalyze *ira,...@@ -6814,6 +6862,31 @@ static TypeTableEntry *ir_analyze_instruction_compile_err(IrAnalyze *ira,
6814 return ira->codegen->builtin_types.entry_invalid;6862 return ira->codegen->builtin_types.entry_invalid;
6815}6863}
68166864
6865static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErrName *instruction) {
6866 IrInstruction *value = instruction->value->other;
6867 if (value->type_entry->id == TypeTableEntryIdInvalid)
6868 return ira->codegen->builtin_types.entry_invalid;
6869
6870 IrInstruction *casted_value = ir_get_casted_value(ira, value, value->type_entry);
6871 if (casted_value->type_entry->id == TypeTableEntryIdInvalid)
6872 return ira->codegen->builtin_types.entry_invalid;
6873
6874 TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
6875 if (casted_value->static_value.special == ConstValSpecialStatic) {
6876 ErrorTableEntry *err = casted_value->static_value.data.x_pure_err;
6877 IrInstruction *new_instruction = ir_create_const_str_lit(&ira->new_irb, instruction->base.scope,
6878 instruction->base.source_node, &err->name);
6879 ir_link_new_instruction(new_instruction, &instruction->base);
6880 new_instruction->static_value.special = ConstValSpecialStatic;
6881 new_instruction->static_value.depends_on_compile_var = casted_value->static_value.depends_on_compile_var;
6882 return str_type;
6883 }
6884
6885 ira->codegen->generate_error_name_table = true;
6886 ir_build_err_name_from(&ira->new_irb, &instruction->base, value);
6887 return str_type;
6888}
6889
6817static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {6890static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
6818 switch (instruction->id) {6891 switch (instruction->id) {
6819 case IrInstructionIdInvalid:6892 case IrInstructionIdInvalid:
...@@ -6904,6 +6977,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -6904,6 +6977,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
6904 return ir_analyze_instruction_max_value(ira, (IrInstructionMaxValue *)instruction);6977 return ir_analyze_instruction_max_value(ira, (IrInstructionMaxValue *)instruction);
6905 case IrInstructionIdCompileErr:6978 case IrInstructionIdCompileErr:
6906 return ir_analyze_instruction_compile_err(ira, (IrInstructionCompileErr *)instruction);6979 return ir_analyze_instruction_compile_err(ira, (IrInstructionCompileErr *)instruction);
6980 case IrInstructionIdErrName:
6981 return ir_analyze_instruction_err_name(ira, (IrInstructionErrName *)instruction);
6907 case IrInstructionIdCast:6982 case IrInstructionIdCast:
6908 case IrInstructionIdStructFieldPtr:6983 case IrInstructionIdStructFieldPtr:
6909 case IrInstructionIdEnumFieldPtr:6984 case IrInstructionIdEnumFieldPtr:
...@@ -7033,6 +7108,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7033,6 +7108,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7033 case IrInstructionIdRef:7108 case IrInstructionIdRef:
7034 case IrInstructionIdMinValue:7109 case IrInstructionIdMinValue:
7035 case IrInstructionIdMaxValue:7110 case IrInstructionIdMaxValue:
7111 case IrInstructionIdErrName:
7036 return false;7112 return false;
7037 case IrInstructionIdAsm:7113 case IrInstructionIdAsm:
7038 {7114 {
...@@ -7103,25 +7179,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7103,25 +7179,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7103// return resolve_expr_const_val_as_import(g, node, child_import);7179// return resolve_expr_const_val_as_import(g, node, child_import);
7104//}7180//}
7105//7181//
7106//static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import,
7107// BlockContext *context, AstNode *node)
7108//{
7109// assert(node->type == NodeTypeFnCallExpr);
7110//
7111// AstNode *err_value = node->data.fn_call_expr.params.at(0);
7112// TypeTableEntry *resolved_type = analyze_expression(g, import, context,
7113// g->builtin_types.entry_pure_error, err_value);
7114//
7115// if (resolved_type->id == TypeTableEntryIdInvalid) {
7116// return resolved_type;
7117// }
7118//
7119// g->generate_error_name_table = true;
7120//
7121// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
7122// return str_type;
7123//}
7124//
7125//static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,7182//static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
7126// BlockContext *context, AstNode *node)7183// BlockContext *context, AstNode *node)
7127//{7184//{
...@@ -7533,8 +7590,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7533,8 +7590,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7533// return analyze_import(g, import, context, node);7590// return analyze_import(g, import, context, node);
7534// case BuiltinFnIdCImport:7591// case BuiltinFnIdCImport:
7535// return analyze_c_import(g, import, context, node);7592// return analyze_c_import(g, import, context, node);
7536// case BuiltinFnIdErrName:
7537// return analyze_err_name(g, import, context, node);
7538// case BuiltinFnIdBreakpoint:7593// case BuiltinFnIdBreakpoint:
7539// mark_impure_fn(g, context, node);7594// mark_impure_fn(g, context, node);
7540// return g->builtin_types.entry_void;7595// return g->builtin_types.entry_void;
...@@ -7927,21 +7982,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7927,21 +7982,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7927// }7982// }
7928//}7983//}
7929//7984//
7930//static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
7931// BlockContext *context, AstNode *node, Buf *err_name)
7932//{
7933// auto err_table_entry = g->error_table.maybe_get(err_name);
7934//
7935// if (err_table_entry) {
7936// return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
7937// }
7938//
7939// add_node_error(g, node,
7940// buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
7941//
7942// return g->builtin_types.entry_invalid;
7943//}
7944//
7945//static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {7985//static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
7946// if (type_entry->id == TypeTableEntryIdMetaType) {7986// if (type_entry->id == TypeTableEntryIdMetaType) {
7947// add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));7987// add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));
...@@ -7952,32 +7992,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -7952,32 +7992,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
7952//7992//
79537993
79547994
7955//static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) {
7956// assert(node->type == NodeTypeFnCallExpr);
7957// assert(g->generate_error_name_table);
7958//
7959// if (g->error_decls.length == 1) {
7960// LLVMBuildUnreachable(g->builder);
7961// return nullptr;
7962// }
7963//
7964//
7965// AstNode *err_val_node = node->data.fn_call_expr.params.at(0);
7966// LLVMValueRef err_val = gen_expr(g, err_val_node);
7967//
7968// if (want_debug_safety(g, node)) {
7969// LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
7970// LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
7971// add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
7972// }
7973//
7974// LLVMValueRef indices[] = {
7975// LLVMConstNull(g->builtin_types.entry_usize->type_ref),
7976// err_val,
7977// };
7978// return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, "");
7979//}
7980//
7981//static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {7995//static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {
7982// assert(node->type == NodeTypeFnCallExpr);7996// assert(node->type == NodeTypeFnCallExpr);
7983//7997//
...@@ -8179,8 +8193,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -8179,8 +8193,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
8179// zig_unreachable();8193// zig_unreachable();
8180// case BuiltinFnIdCompileVar:8194// case BuiltinFnIdCompileVar:
8181// return nullptr;8195// return nullptr;
8182// case BuiltinFnIdErrName:
8183// return gen_err_name(g, node);
8184// case BuiltinFnIdBreakpoint:8196// case BuiltinFnIdBreakpoint:
8185// return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");8197// return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
8186// case BuiltinFnIdFrameAddress:8198// case BuiltinFnIdFrameAddress:
src/ir_print.cpp+9
...@@ -676,6 +676,12 @@ static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruct...@@ -676,6 +676,12 @@ static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruct
676 fprintf(irp->f, ")");676 fprintf(irp->f, ")");
677}677}
678678
679static void ir_print_err_name(IrPrint *irp, IrInstructionErrName *instruction) {
680 fprintf(irp->f, "@errorName(");
681 ir_print_other_instruction(irp, instruction->value);
682 fprintf(irp->f, ")");
683}
684
679static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {685static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
680 ir_print_prefix(irp, instruction);686 ir_print_prefix(irp, instruction);
681 switch (instruction->id) {687 switch (instruction->id) {
...@@ -822,6 +828,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -822,6 +828,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
822 case IrInstructionIdCompileErr:828 case IrInstructionIdCompileErr:
823 ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);829 ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
824 break;830 break;
831 case IrInstructionIdErrName:
832 ir_print_err_name(irp, (IrInstructionErrName *)instruction);
833 break;
825 }834 }
826 fprintf(irp->f, "\n");835 fprintf(irp->f, "\n");
827}836}
test/self_hosted2.zig+21
...@@ -238,6 +238,26 @@ fn testMinValueAndMaxValue() {...@@ -238,6 +238,26 @@ fn testMinValueAndMaxValue() {
238 assert(@minValue(i64) == -9223372036854775808);238 assert(@minValue(i64) == -9223372036854775808);
239}239}
240240
241fn first4KeysOfHomeRow() -> []const u8 {
242 "aoeu"
243}
244
245fn testReturnStringFromFunction() {
246 assert(memeql(first4KeysOfHomeRow(), "aoeu"));
247}
248
249pub fn memeql(a: []const u8, b: []const u8) -> bool {
250 sliceEql(u8, a, b)
251}
252
253pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {
254 if (a.len != b.len) return false;
255 for (a) |item, index| {
256 if (b[index] != item) return false;
257 }
258 return true;
259}
260
241fn assert(ok: bool) {261fn assert(ok: bool) {
242 if (!ok)262 if (!ok)
243 @unreachable();263 @unreachable();
...@@ -263,6 +283,7 @@ fn runAllTests() {...@@ -263,6 +283,7 @@ fn runAllTests() {
263 testStaticAddOne();283 testStaticAddOne();
264 testInlineVarsAgain();284 testInlineVarsAgain();
265 testMinValueAndMaxValue();285 testMinValueAndMaxValue();
286 testReturnStringFromFunction();
266}287}
267288
268export nakedcc fn _start() -> unreachable {289export nakedcc fn _start() -> unreachable {