authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-05 18:51:07-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-05 18:51:07-04:00
log3ff465e2883b556cd08afc08b0a2098255314d4a
tree3315b7dd87d24b7e6de22db6b9cfc0b6e2e70f38
parentc3362c1cb63ff8d8e79a16c76a574bbbd488967c

add OpaqueType builtin

closes #326

6 files changed, 80 insertions(+), 13 deletions(-)

src/all_types.hpp+6
...@@ -1253,6 +1253,7 @@ enum BuiltinFnId {...@@ -1253,6 +1253,7 @@ enum BuiltinFnId {
1253 BuiltinFnIdShrExact,1253 BuiltinFnIdShrExact,
1254 BuiltinFnIdSetEvalBranchQuota,1254 BuiltinFnIdSetEvalBranchQuota,
1255 BuiltinFnIdAlignCast,1255 BuiltinFnIdAlignCast,
1256 BuiltinFnIdOpaqueType,
1256};1257};
12571258
1258struct BuiltinFnEntry {1259struct BuiltinFnEntry {
...@@ -1858,6 +1859,7 @@ enum IrInstructionId {...@@ -1858,6 +1859,7 @@ enum IrInstructionId {
1858 IrInstructionIdSetEvalBranchQuota,1859 IrInstructionIdSetEvalBranchQuota,
1859 IrInstructionIdPtrTypeOf,1860 IrInstructionIdPtrTypeOf,
1860 IrInstructionIdAlignCast,1861 IrInstructionIdAlignCast,
1862 IrInstructionIdOpaqueType,
1861};1863};
18621864
1863struct IrInstruction {1865struct IrInstruction {
...@@ -2648,6 +2650,10 @@ struct IrInstructionAlignCast {...@@ -2648,6 +2650,10 @@ struct IrInstructionAlignCast {
2648 IrInstruction *target;2650 IrInstruction *target;
2649};2651};
26502652
2653struct IrInstructionOpaqueType {
2654 IrInstruction base;
2655};
2656
2651static const size_t slice_ptr_index = 0;2657static const size_t slice_ptr_index = 0;
2652static const size_t slice_len_index = 1;2658static const size_t slice_len_index = 1;
26532659
src/codegen.cpp+4-1
...@@ -469,7 +469,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -469,7 +469,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
469 FnTableEntry *fn_table_entry = fn_scope->fn_entry;469 FnTableEntry *fn_table_entry = fn_scope->fn_entry;
470 if (!fn_table_entry->proto_node)470 if (!fn_table_entry->proto_node)
471 return get_di_scope(g, scope->parent);471 return get_di_scope(g, scope->parent);
472 unsigned line_number = (unsigned)fn_table_entry->proto_node->line + 1;472 unsigned line_number = (unsigned)(fn_table_entry->proto_node->line == 0) ?
473 0 : (fn_table_entry->proto_node->line + 1);
473 unsigned scope_line = line_number;474 unsigned scope_line = line_number;
474 bool is_definition = fn_table_entry->body_node != nullptr;475 bool is_definition = fn_table_entry->body_node != nullptr;
475 unsigned flags = 0;476 unsigned flags = 0;
...@@ -3328,6 +3329,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3328,6 +3329,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3328 case IrInstructionIdTypeId:3329 case IrInstructionIdTypeId:
3329 case IrInstructionIdSetEvalBranchQuota:3330 case IrInstructionIdSetEvalBranchQuota:
3330 case IrInstructionIdPtrTypeOf:3331 case IrInstructionIdPtrTypeOf:
3332 case IrInstructionIdOpaqueType:
3331 zig_unreachable();3333 zig_unreachable();
3332 case IrInstructionIdReturn:3334 case IrInstructionIdReturn:
3333 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);3335 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -4732,6 +4734,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -4732,6 +4734,7 @@ static void define_builtin_fns(CodeGen *g) {
4732 create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);4734 create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
4733 create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);4735 create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);
4734 create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);4736 create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);
4737 create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0);
4735}4738}
47364739
4737static const char *bool_to_str(bool b) {4740static const char *bool_to_str(bool b) {
src/ir.cpp+44-12
...@@ -559,6 +559,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {...@@ -559,6 +559,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
559 return IrInstructionIdAlignCast;559 return IrInstructionIdAlignCast;
560}560}
561561
562static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
563 return IrInstructionIdOpaqueType;
564}
565
562template<typename T>566template<typename T>
563static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {567static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
564 T *special_instruction = allocate<T>(1);568 T *special_instruction = allocate<T>(1);
...@@ -2238,6 +2242,12 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode...@@ -2238,6 +2242,12 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
2238 return &instruction->base;2242 return &instruction->base;
2239}2243}
22402244
2245static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2246 IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
2247
2248 return &instruction->base;
2249}
2250
2241static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {2251static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
2242 return nullptr;2252 return nullptr;
2243}2253}
...@@ -2956,6 +2966,10 @@ static IrInstruction *ir_instruction_aligncast_get_dep(IrInstructionAlignCast *i...@@ -2956,6 +2966,10 @@ static IrInstruction *ir_instruction_aligncast_get_dep(IrInstructionAlignCast *i
2956 }2966 }
2957}2967}
29582968
2969static IrInstruction *ir_instruction_opaquetype_get_dep(IrInstructionOpaqueType *instruction, size_t index) {
2970 return nullptr;
2971}
2972
2959static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {2973static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
2960 switch (instruction->id) {2974 switch (instruction->id) {
2961 case IrInstructionIdInvalid:2975 case IrInstructionIdInvalid:
...@@ -3154,6 +3168,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -3154,6 +3168,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
3154 return ir_instruction_ptrtypeof_get_dep((IrInstructionPtrTypeOf *) instruction, index);3168 return ir_instruction_ptrtypeof_get_dep((IrInstructionPtrTypeOf *) instruction, index);
3155 case IrInstructionIdAlignCast:3169 case IrInstructionIdAlignCast:
3156 return ir_instruction_aligncast_get_dep((IrInstructionAlignCast *) instruction, index);3170 return ir_instruction_aligncast_get_dep((IrInstructionAlignCast *) instruction, index);
3171 case IrInstructionIdOpaqueType:
3172 return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index);
3157 }3173 }
3158 zig_unreachable();3174 zig_unreachable();
3159}3175}
...@@ -4578,6 +4594,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4578,6 +4594,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
45784594
4579 return ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);4595 return ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);
4580 }4596 }
4597 case BuiltinFnIdOpaqueType:
4598 return ir_build_opaque_type(irb, scope, node);
4581 }4599 }
4582 zig_unreachable();4600 zig_unreachable();
4583}4601}
...@@ -6044,27 +6062,30 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o...@@ -6044,27 +6062,30 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
6044 return true;6062 return true;
6045}6063}
60466064
6047static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6065static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, AstNode *source_node) {
6048 assert(node->type == NodeTypeContainerDecl);6066 if (exec->name) {
60496067 return exec->name;
6050 ContainerKind kind = node->data.container_decl.kind;
6051 Buf *name;
6052 if (irb->exec->name) {
6053 name = irb->exec->name;
6054 } else {6068 } else {
6055 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);6069 FnTableEntry *fn_entry = exec_fn_entry(exec);
6056 if (fn_entry) {6070 if (fn_entry) {
6057 name = buf_alloc();6071 Buf *name = buf_alloc();
6058 buf_append_buf(name, &fn_entry->symbol_name);6072 buf_append_buf(name, &fn_entry->symbol_name);
6059 buf_appendf(name, "(");6073 buf_appendf(name, "(");
6060 render_instance_name_recursive(irb->codegen, name, &fn_entry->fndef_scope->base, irb->exec->begin_scope);6074 render_instance_name_recursive(codegen, name, &fn_entry->fndef_scope->base, exec->begin_scope);
6061 buf_appendf(name, ")");6075 buf_appendf(name, ")");
6076 return name;
6062 } else {6077 } else {
6063 name = buf_sprintf("(anonymous %s at %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", container_string(kind),6078 return buf_sprintf("(anonymous %s at %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", kind_name,
6064 buf_ptr(node->owner->path), node->line + 1, node->column + 1);6079 buf_ptr(source_node->owner->path), source_node->line + 1, source_node->column + 1);
6065 }6080 }
6066 }6081 }
6082}
60676083
6084static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6085 assert(node->type == NodeTypeContainerDecl);
6086
6087 ContainerKind kind = node->data.container_decl.kind;
6088 Buf *name = get_anon_type_name(irb->codegen, irb->exec, container_string(kind), node);
60686089
6069 VisibMod visib_mod = VisibModPub;6090 VisibMod visib_mod = VisibModPub;
6070 TldContainer *tld_container = allocate<TldContainer>(1);6091 TldContainer *tld_container = allocate<TldContainer>(1);
...@@ -15143,6 +15164,14 @@ static TypeTableEntry *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstr...@@ -15143,6 +15164,14 @@ static TypeTableEntry *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstr
15143 return result->value.type;15164 return result->value.type;
15144}15165}
1514515166
15167static TypeTableEntry *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstructionOpaqueType *instruction) {
15168 Buf *name = get_anon_type_name(ira->codegen, ira->new_irb.exec, "opaque", instruction->base.source_node);
15169 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
15170 out_val->data.x_type = get_opaque_type(ira->codegen, instruction->base.scope, instruction->base.source_node,
15171 buf_ptr(name));
15172 return ira->codegen->builtin_types.entry_type;
15173}
15174
15146static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {15175static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
15147 switch (instruction->id) {15176 switch (instruction->id) {
15148 case IrInstructionIdInvalid:15177 case IrInstructionIdInvalid:
...@@ -15329,6 +15358,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -15329,6 +15358,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
15329 return ir_analyze_instruction_ptr_type_of(ira, (IrInstructionPtrTypeOf *)instruction);15358 return ir_analyze_instruction_ptr_type_of(ira, (IrInstructionPtrTypeOf *)instruction);
15330 case IrInstructionIdAlignCast:15359 case IrInstructionIdAlignCast:
15331 return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);15360 return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
15361 case IrInstructionIdOpaqueType:
15362 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
15332 }15363 }
15333 zig_unreachable();15364 zig_unreachable();
15334}15365}
...@@ -15507,6 +15538,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -15507,6 +15538,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
15507 case IrInstructionIdOffsetOf:15538 case IrInstructionIdOffsetOf:
15508 case IrInstructionIdTypeId:15539 case IrInstructionIdTypeId:
15509 case IrInstructionIdAlignCast:15540 case IrInstructionIdAlignCast:
15541 case IrInstructionIdOpaqueType:
15510 return false;15542 return false;
15511 case IrInstructionIdAsm:15543 case IrInstructionIdAsm:
15512 {15544 {
src/ir_print.cpp+7
...@@ -944,6 +944,10 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio...@@ -944,6 +944,10 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio
944 fprintf(irp->f, ")");944 fprintf(irp->f, ")");
945}945}
946946
947static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
948 fprintf(irp->f, "@OpaqueType()");
949}
950
947static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {951static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
948 ir_print_prefix(irp, instruction);952 ir_print_prefix(irp, instruction);
949 switch (instruction->id) {953 switch (instruction->id) {
...@@ -1240,6 +1244,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1240,6 +1244,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1240 case IrInstructionIdAlignCast:1244 case IrInstructionIdAlignCast:
1241 ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);1245 ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);
1242 break;1246 break;
1247 case IrInstructionIdOpaqueType:
1248 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
1249 break;
1243 }1250 }
1244 fprintf(irp->f, "\n");1251 fprintf(irp->f, "\n");
1245}1252}
test/cases/misc.zig+8
...@@ -538,3 +538,11 @@ export fn writeToVRam() {...@@ -538,3 +538,11 @@ export fn writeToVRam() {
538test "pointer child field" {538test "pointer child field" {
539 assert((&u32).child == u32);539 assert((&u32).child == u32);
540}540}
541
542const OpaqueA = @OpaqueType();
543const OpaqueB = @OpaqueType();
544test "@OpaqueType" {
545 assert(&OpaqueA != &OpaqueB);
546 assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
547 assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
548}
test/compile_errors.zig+11
...@@ -2079,4 +2079,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2079,4 +2079,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2079 ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack",2079 ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack",
2080 ".tmp_source.zig:2:8: note: called from here",2080 ".tmp_source.zig:2:8: note: called from here",
2081 ".tmp_source.zig:1:10: note: called from here");2081 ".tmp_source.zig:1:10: note: called from here");
2082
2083 cases.add("wrong pointer implicitly casted to pointer to @OpaqueType()",
2084 \\const Derp = @OpaqueType();
2085 \\extern fn bar(d: &Derp);
2086 \\export fn foo() {
2087 \\ const x = u8(1);
2088 \\ bar(@ptrCast(&c_void, &x));
2089 \\}
2090 ,
2091 ".tmp_source.zig:5:9: error: expected type '&Derp', found '&c_void'");
2092
2082}2093}