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 {
12531253 BuiltinFnIdShrExact,
12541254 BuiltinFnIdSetEvalBranchQuota,
12551255 BuiltinFnIdAlignCast,
1256 BuiltinFnIdOpaqueType,
12561257};
12571258
12581259struct BuiltinFnEntry {
......@@ -1858,6 +1859,7 @@ enum IrInstructionId {
18581859 IrInstructionIdSetEvalBranchQuota,
18591860 IrInstructionIdPtrTypeOf,
18601861 IrInstructionIdAlignCast,
1862 IrInstructionIdOpaqueType,
18611863};
18621864
18631865struct IrInstruction {
......@@ -2648,6 +2650,10 @@ struct IrInstructionAlignCast {
26482650 IrInstruction *target;
26492651};
26502652
2653struct IrInstructionOpaqueType {
2654 IrInstruction base;
2655};
2656
26512657static const size_t slice_ptr_index = 0;
26522658static 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) {
469469 FnTableEntry *fn_table_entry = fn_scope->fn_entry;
470470 if (!fn_table_entry->proto_node)
471471 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);
473474 unsigned scope_line = line_number;
474475 bool is_definition = fn_table_entry->body_node != nullptr;
475476 unsigned flags = 0;
......@@ -3328,6 +3329,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
33283329 case IrInstructionIdTypeId:
33293330 case IrInstructionIdSetEvalBranchQuota:
33303331 case IrInstructionIdPtrTypeOf:
3332 case IrInstructionIdOpaqueType:
33313333 zig_unreachable();
33323334 case IrInstructionIdReturn:
33333335 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -4732,6 +4734,7 @@ static void define_builtin_fns(CodeGen *g) {
47324734 create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
47334735 create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);
47344736 create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);
4737 create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0);
47354738}
47364739
47374740static const char *bool_to_str(bool b) {
src/ir.cpp+44-12
......@@ -559,6 +559,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
559559 return IrInstructionIdAlignCast;
560560}
561561
562static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
563 return IrInstructionIdOpaqueType;
564}
565
562566template<typename T>
563567static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
564568 T *special_instruction = allocate<T>(1);
......@@ -2238,6 +2242,12 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
22382242 return &instruction->base;
22392243}
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
22412251static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
22422252 return nullptr;
22432253}
......@@ -2956,6 +2966,10 @@ static IrInstruction *ir_instruction_aligncast_get_dep(IrInstructionAlignCast *i
29562966 }
29572967}
29582968
2969static IrInstruction *ir_instruction_opaquetype_get_dep(IrInstructionOpaqueType *instruction, size_t index) {
2970 return nullptr;
2971}
2972
29592973static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
29602974 switch (instruction->id) {
29612975 case IrInstructionIdInvalid:
......@@ -3154,6 +3168,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
31543168 return ir_instruction_ptrtypeof_get_dep((IrInstructionPtrTypeOf *) instruction, index);
31553169 case IrInstructionIdAlignCast:
31563170 return ir_instruction_aligncast_get_dep((IrInstructionAlignCast *) instruction, index);
3171 case IrInstructionIdOpaqueType:
3172 return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index);
31573173 }
31583174 zig_unreachable();
31593175}
......@@ -4578,6 +4594,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
45784594
45794595 return ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);
45804596 }
4597 case BuiltinFnIdOpaqueType:
4598 return ir_build_opaque_type(irb, scope, node);
45814599 }
45824600 zig_unreachable();
45834601}
......@@ -6044,27 +6062,30 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
60446062 return true;
60456063}
60466064
6047static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6048 assert(node->type == NodeTypeContainerDecl);
6049
6050 ContainerKind kind = node->data.container_decl.kind;
6051 Buf *name;
6052 if (irb->exec->name) {
6053 name = irb->exec->name;
6065static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, AstNode *source_node) {
6066 if (exec->name) {
6067 return exec->name;
60546068 } else {
6055 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
6069 FnTableEntry *fn_entry = exec_fn_entry(exec);
60566070 if (fn_entry) {
6057 name = buf_alloc();
6071 Buf *name = buf_alloc();
60586072 buf_append_buf(name, &fn_entry->symbol_name);
60596073 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);
60616075 buf_appendf(name, ")");
6076 return name;
60626077 } else {
6063 name = buf_sprintf("(anonymous %s at %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", container_string(kind),
6064 buf_ptr(node->owner->path), node->line + 1, node->column + 1);
6078 return buf_sprintf("(anonymous %s at %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", kind_name,
6079 buf_ptr(source_node->owner->path), source_node->line + 1, source_node->column + 1);
60656080 }
60666081 }
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
60696090 VisibMod visib_mod = VisibModPub;
60706091 TldContainer *tld_container = allocate<TldContainer>(1);
......@@ -15143,6 +15164,14 @@ static TypeTableEntry *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstr
1514315164 return result->value.type;
1514415165}
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
1514615175static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1514715176 switch (instruction->id) {
1514815177 case IrInstructionIdInvalid:
......@@ -15329,6 +15358,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1532915358 return ir_analyze_instruction_ptr_type_of(ira, (IrInstructionPtrTypeOf *)instruction);
1533015359 case IrInstructionIdAlignCast:
1533115360 return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
15361 case IrInstructionIdOpaqueType:
15362 return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
1533215363 }
1533315364 zig_unreachable();
1533415365}
......@@ -15507,6 +15538,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1550715538 case IrInstructionIdOffsetOf:
1550815539 case IrInstructionIdTypeId:
1550915540 case IrInstructionIdAlignCast:
15541 case IrInstructionIdOpaqueType:
1551015542 return false;
1551115543 case IrInstructionIdAsm:
1551215544 {
src/ir_print.cpp+7
......@@ -944,6 +944,10 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio
944944 fprintf(irp->f, ")");
945945}
946946
947static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
948 fprintf(irp->f, "@OpaqueType()");
949}
950
947951static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
948952 ir_print_prefix(irp, instruction);
949953 switch (instruction->id) {
......@@ -1240,6 +1244,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
12401244 case IrInstructionIdAlignCast:
12411245 ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);
12421246 break;
1247 case IrInstructionIdOpaqueType:
1248 ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
1249 break;
12431250 }
12441251 fprintf(irp->f, "\n");
12451252}
test/cases/misc.zig+8
......@@ -538,3 +538,11 @@ export fn writeToVRam() {
538538test "pointer child field" {
539539 assert((&u32).child == u32);
540540}
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) {
20792079 ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack",
20802080 ".tmp_source.zig:2:8: note: called from here",
20812081 ".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
20822093}