Commit 3ff465e288
Changed files (6)
src/all_types.hpp
@@ -1253,6 +1253,7 @@ enum BuiltinFnId {
BuiltinFnIdShrExact,
BuiltinFnIdSetEvalBranchQuota,
BuiltinFnIdAlignCast,
+ BuiltinFnIdOpaqueType,
};
struct BuiltinFnEntry {
@@ -1858,6 +1859,7 @@ enum IrInstructionId {
IrInstructionIdSetEvalBranchQuota,
IrInstructionIdPtrTypeOf,
IrInstructionIdAlignCast,
+ IrInstructionIdOpaqueType,
};
struct IrInstruction {
@@ -2648,6 +2650,10 @@ struct IrInstructionAlignCast {
IrInstruction *target;
};
+struct IrInstructionOpaqueType {
+ IrInstruction base;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
src/codegen.cpp
@@ -469,7 +469,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
FnTableEntry *fn_table_entry = fn_scope->fn_entry;
if (!fn_table_entry->proto_node)
return get_di_scope(g, scope->parent);
- unsigned line_number = (unsigned)fn_table_entry->proto_node->line + 1;
+ unsigned line_number = (unsigned)(fn_table_entry->proto_node->line == 0) ?
+ 0 : (fn_table_entry->proto_node->line + 1);
unsigned scope_line = line_number;
bool is_definition = fn_table_entry->body_node != nullptr;
unsigned flags = 0;
@@ -3328,6 +3329,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdTypeId:
case IrInstructionIdSetEvalBranchQuota:
case IrInstructionIdPtrTypeOf:
+ case IrInstructionIdOpaqueType:
zig_unreachable();
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
@@ -4732,6 +4734,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);
create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);
+ create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0);
}
static const char *bool_to_str(bool b) {
src/ir.cpp
@@ -559,6 +559,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) {
return IrInstructionIdAlignCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) {
+ return IrInstructionIdOpaqueType;
+}
+
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -2238,6 +2242,12 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) {
+ IrInstructionOpaqueType *instruction = ir_build_instruction<IrInstructionOpaqueType>(irb, scope, source_node);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
return nullptr;
}
@@ -2956,6 +2966,10 @@ static IrInstruction *ir_instruction_aligncast_get_dep(IrInstructionAlignCast *i
}
}
+static IrInstruction *ir_instruction_opaquetype_get_dep(IrInstructionOpaqueType *instruction, size_t index) {
+ return nullptr;
+}
+
static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -3154,6 +3168,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_ptrtypeof_get_dep((IrInstructionPtrTypeOf *) instruction, index);
case IrInstructionIdAlignCast:
return ir_instruction_aligncast_get_dep((IrInstructionAlignCast *) instruction, index);
+ case IrInstructionIdOpaqueType:
+ return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index);
}
zig_unreachable();
}
@@ -4578,6 +4594,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_align_cast(irb, scope, node, arg0_value, arg1_value);
}
+ case BuiltinFnIdOpaqueType:
+ return ir_build_opaque_type(irb, scope, node);
}
zig_unreachable();
}
@@ -6044,27 +6062,30 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
return true;
}
-static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
- assert(node->type == NodeTypeContainerDecl);
-
- ContainerKind kind = node->data.container_decl.kind;
- Buf *name;
- if (irb->exec->name) {
- name = irb->exec->name;
+static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, AstNode *source_node) {
+ if (exec->name) {
+ return exec->name;
} else {
- FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
+ FnTableEntry *fn_entry = exec_fn_entry(exec);
if (fn_entry) {
- name = buf_alloc();
+ Buf *name = buf_alloc();
buf_append_buf(name, &fn_entry->symbol_name);
buf_appendf(name, "(");
- render_instance_name_recursive(irb->codegen, name, &fn_entry->fndef_scope->base, irb->exec->begin_scope);
+ render_instance_name_recursive(codegen, name, &fn_entry->fndef_scope->base, exec->begin_scope);
buf_appendf(name, ")");
+ return name;
} else {
- name = buf_sprintf("(anonymous %s at %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", container_string(kind),
- buf_ptr(node->owner->path), node->line + 1, node->column + 1);
+ return buf_sprintf("(anonymous %s at %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", kind_name,
+ buf_ptr(source_node->owner->path), source_node->line + 1, source_node->column + 1);
}
}
+}
+static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
+ assert(node->type == NodeTypeContainerDecl);
+
+ ContainerKind kind = node->data.container_decl.kind;
+ Buf *name = get_anon_type_name(irb->codegen, irb->exec, container_string(kind), node);
VisibMod visib_mod = VisibModPub;
TldContainer *tld_container = allocate<TldContainer>(1);
@@ -15143,6 +15164,14 @@ static TypeTableEntry *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstr
return result->value.type;
}
+static TypeTableEntry *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstructionOpaqueType *instruction) {
+ Buf *name = get_anon_type_name(ira->codegen, ira->new_irb.exec, "opaque", instruction->base.source_node);
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ out_val->data.x_type = get_opaque_type(ira->codegen, instruction->base.scope, instruction->base.source_node,
+ buf_ptr(name));
+ return ira->codegen->builtin_types.entry_type;
+}
+
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -15329,6 +15358,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_ptr_type_of(ira, (IrInstructionPtrTypeOf *)instruction);
case IrInstructionIdAlignCast:
return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction);
+ case IrInstructionIdOpaqueType:
+ return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction);
}
zig_unreachable();
}
@@ -15507,6 +15538,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdOffsetOf:
case IrInstructionIdTypeId:
case IrInstructionIdAlignCast:
+ case IrInstructionIdOpaqueType:
return false;
case IrInstructionIdAsm:
{
src/ir_print.cpp
@@ -944,6 +944,10 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio
fprintf(irp->f, ")");
}
+static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) {
+ fprintf(irp->f, "@OpaqueType()");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1240,6 +1244,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAlignCast:
ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction);
break;
+ case IrInstructionIdOpaqueType:
+ ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
test/cases/misc.zig
@@ -538,3 +538,11 @@ export fn writeToVRam() {
test "pointer child field" {
assert((&u32).child == u32);
}
+
+const OpaqueA = @OpaqueType();
+const OpaqueB = @OpaqueType();
+test "@OpaqueType" {
+ assert(&OpaqueA != &OpaqueB);
+ assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
+ assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
+}
test/compile_errors.zig
@@ -2079,4 +2079,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack",
".tmp_source.zig:2:8: note: called from here",
".tmp_source.zig:1:10: note: called from here");
+
+ cases.add("wrong pointer implicitly casted to pointer to @OpaqueType()",
+ \\const Derp = @OpaqueType();
+ \\extern fn bar(d: &Derp);
+ \\export fn foo() {
+ \\ const x = u8(1);
+ \\ bar(@ptrCast(&c_void, &x));
+ \\}
+ ,
+ ".tmp_source.zig:5:9: error: expected type '&Derp', found '&c_void'");
+
}