authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-22 10:39:10-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-22 10:39:10-05:00
log6f91fb4c37a676002ccb68b78bea8044ba44b7e2
tree4500d5a03322813bb1f09b4a226a83cec939938b
parent8dc45bc50523d9fa58a937f525b9dc8f7569af0b

IR: support const ref


4 files changed, 60 insertions(+), 17 deletions(-)

src/all_types.hpp+2
...@@ -1849,6 +1849,7 @@ struct IrInstructionRef {...@@ -1849,6 +1849,7 @@ struct IrInstructionRef {
18491849
1850 IrInstruction *value;1850 IrInstruction *value;
1851 LLVMValueRef tmp_ptr;1851 LLVMValueRef tmp_ptr;
1852 bool is_const;
1852};1853};
18531854
1854struct IrInstructionMinValue {1855struct IrInstructionMinValue {
...@@ -2099,6 +2100,7 @@ enum LValPurpose {...@@ -2099,6 +2100,7 @@ enum LValPurpose {
2099 LValPurposeNone,2100 LValPurposeNone,
2100 LValPurposeAssign,2101 LValPurposeAssign,
2101 LValPurposeAddressOf,2102 LValPurposeAddressOf,
2103 LValPurposeAddressOfConst,
2102};2104};
21032105
2104static const size_t slice_ptr_index = 0;2106static const size_t slice_ptr_index = 0;
src/ir.cpp+25-16
...@@ -1399,17 +1399,23 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode *...@@ -1399,17 +1399,23 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode *
1399 return &instruction->base;1399 return &instruction->base;
1400}1400}
14011401
1402static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1402static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
1403 bool is_const)
1404{
1403 IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node);1405 IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node);
1404 instruction->value = value;1406 instruction->value = value;
1407 instruction->is_const = is_const;
14051408
1406 ir_ref_instruction(value);1409 ir_ref_instruction(value);
14071410
1408 return &instruction->base;1411 return &instruction->base;
1409}1412}
14101413
1411static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {1414static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value,
1412 IrInstruction *new_instruction = ir_build_ref(irb, old_instruction->scope, old_instruction->source_node, value);1415 bool is_const)
1416{
1417 IrInstruction *new_instruction = ir_build_ref(irb, old_instruction->scope, old_instruction->source_node,
1418 value, is_const);
1413 ir_link_new_instruction(new_instruction, old_instruction);1419 ir_link_new_instruction(new_instruction, old_instruction);
1414 return new_instruction;1420 return new_instruction;
1415}1421}
...@@ -2479,7 +2485,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld...@@ -2479,7 +2485,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld
2479 assert(fn_entry->type_entry);2485 assert(fn_entry->type_entry);
2480 IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry);2486 IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry);
2481 if (lval != LValPurposeNone)2487 if (lval != LValPurposeNone)
2482 return ir_build_ref(irb, scope, source_node, ref_instruction);2488 return ir_build_ref(irb, scope, source_node, ref_instruction, true);
2483 else2489 else
2484 return ref_instruction;2490 return ref_instruction;
2485 }2491 }
...@@ -2489,7 +2495,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld...@@ -2489,7 +2495,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld
2489 TypeTableEntry *typedef_type = tld_typedef->type_entry;2495 TypeTableEntry *typedef_type = tld_typedef->type_entry;
2490 IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type);2496 IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type);
2491 if (lval != LValPurposeNone)2497 if (lval != LValPurposeNone)
2492 return ir_build_ref(irb, scope, source_node, ref_instruction);2498 return ir_build_ref(irb, scope, source_node, ref_instruction, true);
2493 else2499 else
2494 return ref_instruction;2500 return ref_instruction;
2495 }2501 }
...@@ -2506,7 +2512,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -2506,7 +2512,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
2506 if (primitive_table_entry) {2512 if (primitive_table_entry) {
2507 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);2513 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);
2508 if (lval != LValPurposeNone) {2514 if (lval != LValPurposeNone) {
2509 return ir_build_ref(irb, scope, node, value);2515 return ir_build_ref(irb, scope, node, value, lval == LValPurposeAddressOfConst);
2510 } else {2516 } else {
2511 return value;2517 return value;
2512 }2518 }
...@@ -3105,14 +3111,15 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *...@@ -3105,14 +3111,15 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
31053111
3106 // We needed a pointer to a value, but we got a value. So we create3112 // We needed a pointer to a value, but we got a value. So we create
3107 // an instruction which just makes a const pointer of it.3113 // an instruction which just makes a const pointer of it.
3108 return ir_build_ref(irb, scope, value->source_node, value);3114 return ir_build_ref(irb, scope, value->source_node, value, true);
3109}3115}
31103116
3111static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) {3117static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) {
3112 assert(node->type == NodeTypePrefixOpExpr);3118 assert(node->type == NodeTypePrefixOpExpr);
3113 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;3119 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
31143120
3115 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf);3121 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope,
3122 is_const ? LValPurposeAddressOfConst : LValPurposeAddressOf);
3116 if (value == irb->codegen->invalid_instruction)3123 if (value == irb->codegen->invalid_instruction)
3117 return value;3124 return value;
31183125
...@@ -5102,7 +5109,8 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_...@@ -5102,7 +5109,8 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
5102 IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value;5109 IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value;
5103 return load_ptr_inst->ptr;5110 return load_ptr_inst->ptr;
5104 } else {5111 } else {
5105 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope, source_instr->source_node, value);5112 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope,
5113 source_instr->source_node, value, true);
51065114
5107 TypeTableEntry *child_type = wanted_type->data.pointer.child_type;5115 TypeTableEntry *child_type = wanted_type->data.pointer.child_type;
5108 if (type_has_bits(child_type)) {5116 if (type_has_bits(child_type)) {
...@@ -5454,7 +5462,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -5454,7 +5462,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
5454 }5462 }
5455}5463}
54565464
5457static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value) {5465static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,
5466 bool is_const)
5467{
5458 if (value->type_entry->id == TypeTableEntryIdInvalid)5468 if (value->type_entry->id == TypeTableEntryIdInvalid)
5459 return ira->codegen->builtin_types.entry_invalid;5469 return ira->codegen->builtin_types.entry_invalid;
54605470
...@@ -5462,15 +5472,14 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst...@@ -5462,15 +5472,14 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
5462 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);5472 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
5463 if (!val)5473 if (!val)
5464 return ira->codegen->builtin_types.entry_invalid;5474 return ira->codegen->builtin_types.entry_invalid;
5465 bool ptr_is_const = false;
5466 return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry,5475 return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry,
5467 false, ConstPtrSpecialNone, ptr_is_const);5476 false, ConstPtrSpecialNone, is_const);
5468 }5477 }
54695478
5470 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true);5479 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true);
5471 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);5480 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
5472 assert(fn_entry);5481 assert(fn_entry);
5473 IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, value);5482 IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, value, is_const);
5474 fn_entry->alloca_list.append(new_instruction);5483 fn_entry->alloca_list.append(new_instruction);
5475 return ptr_type;5484 return ptr_type;
5476}5485}
...@@ -6986,7 +6995,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc...@@ -6986,7 +6995,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
6986 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special, var->src_is_const);6995 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special, var->src_is_const);
6987 } else {6996 } else {
6988 ir_build_var_ptr_from(&ira->new_irb, instruction, var);6997 ir_build_var_ptr_from(&ira->new_irb, instruction, var);
6989 return get_pointer_to_type(ira->codegen, var->type, false);6998 return get_pointer_to_type(ira->codegen, var->type, var->src_is_const);
6990 }6999 }
6991}7000}
69927001
...@@ -7130,7 +7139,7 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -7130,7 +7139,7 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
7130 bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var;7139 bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var;
7131 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope,7140 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope,
7132 field_ptr_instruction->base.source_node, fn_entry, container_ptr, depends_on_compile_var);7141 field_ptr_instruction->base.source_node, fn_entry, container_ptr, depends_on_compile_var);
7133 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value);7142 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true);
7134 }7143 }
7135 }7144 }
7136 ir_add_error_node(ira, field_ptr_instruction->base.source_node,7145 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
...@@ -8413,7 +8422,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,...@@ -8413,7 +8422,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
84138422
8414static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) {8423static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) {
8415 IrInstruction *value = ref_instruction->value->other;8424 IrInstruction *value = ref_instruction->value->other;
8416 return ir_analyze_ref(ira, &ref_instruction->base, value);8425 return ir_analyze_ref(ira, &ref_instruction->base, value, ref_instruction->is_const);
8417}8426}
84188427
8419static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,8428static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
src/ir_print.cpp+2-1
...@@ -666,7 +666,8 @@ static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction)...@@ -666,7 +666,8 @@ static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction)
666}666}
667667
668static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {668static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
669 fprintf(irp->f, "ref ");669 const char *const_str = instruction->is_const ? "const " : "";
670 fprintf(irp->f, "%sref ", const_str);
670 ir_print_other_instruction(irp, instruction->value);671 ir_print_other_instruction(irp, instruction->value);
671}672}
672673
test/cases3/misc.zig+31
...@@ -242,6 +242,24 @@ fn multilineString() {...@@ -242,6 +242,24 @@ fn multilineString() {
242 assert(memeql(s1, s2));242 assert(memeql(s1, s2));
243}243}
244244
245fn multilineCString() {
246 @setFnTest(this);
247
248 const s1 =
249 c\\one
250 c\\two)
251 c\\three
252 ;
253 const s2 = c"one\ntwo)\nthree";
254 assert(cstrcmp(s1, s2) == 0);
255}
256
257
258fn typeEquality() {
259 @setFnTest(this);
260
261 assert(&const u8 != &u8);
262}
245263
246// TODO import from std.str264// TODO import from std.str
247pub fn memeql(a: []const u8, b: []const u8) -> bool {265pub fn memeql(a: []const u8, b: []const u8) -> bool {
...@@ -257,6 +275,19 @@ pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {...@@ -257,6 +275,19 @@ pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {
257 return true;275 return true;
258}276}
259277
278// TODO import from std.cstr
279pub fn cstrcmp(a: &const u8, b: &const u8) -> i8 {
280 var index: usize = 0;
281 while (a[index] == b[index] && a[index] != 0; index += 1) {}
282 return if (a[index] > b[index]) {
283 1
284 } else if (a[index] < b[index]) {
285 -1
286 } else {
287 i8(0)
288 };
289}
290
260291
261// TODO const assert = @import("std").debug.assert;292// TODO const assert = @import("std").debug.assert;
262fn assert(ok: bool) {293fn assert(ok: bool) {