diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index b5f439ec27..795aeda5ed 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -113,6 +113,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .Period => return rlWrap(mod, scope, rl, try field(mod, scope, node.castTag(.Period).?)), .Deref => return rlWrap(mod, scope, rl, try deref(mod, scope, node.castTag(.Deref).?)), .BoolNot => return rlWrap(mod, scope, rl, try boolNot(mod, scope, node.castTag(.BoolNot).?)), + .AddressOf => return rlWrap(mod, scope, rl, try addressOf(mod, scope, node.castTag(.AddressOf).?)), .FloatLiteral => return rlWrap(mod, scope, rl, try floatLiteral(mod, scope, node.castTag(.FloatLiteral).?)), .UndefinedLiteral => return rlWrap(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)), .BoolLiteral => return rlWrap(mod, scope, rl, try boolLiteral(mod, scope, node.castTag(.BoolLiteral).?)), @@ -122,6 +123,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .Block => return rlWrapVoid(mod, scope, rl, node, try blockExpr(mod, scope, node.castTag(.Block).?)), .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?), .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)), + .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)), .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}), @@ -131,7 +133,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}), .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}), .OrElse => return mod.failNode(scope, node, "TODO implement astgen.expr for .OrElse", .{}), - .AddressOf => return mod.failNode(scope, node, "TODO implement astgen.expr for .AddressOf", .{}), .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}), .BitNot => return mod.failNode(scope, node, "TODO implement astgen.expr for .BitNot", .{}), .Negation => return mod.failNode(scope, node, "TODO implement astgen.expr for .Negation", .{}), @@ -140,7 +141,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), .ArrayType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayType", .{}), .ArrayTypeSentinel => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayTypeSentinel", .{}), - .PtrType => return mod.failNode(scope, node, "TODO implement astgen.expr for .PtrType", .{}), .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}), .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}), .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}), @@ -452,6 +452,12 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr return addZIRUnOp(mod, scope, src, .boolnot, operand); } +fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.op_token].start; + return expr(mod, scope, .lvalue, node.rhs); +} + fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { const tree = scope.tree(); const src = tree.token_locs[node.op_token].start; @@ -463,6 +469,47 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn return addZIRUnOp(mod, scope, src, .optional_type, operand); } +fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.op_token].start; + const meta_type = try addZIRInstConst(mod, scope, src, .{ + .ty = Type.initTag(.type), + .val = Value.initTag(.type_type), + }); + + const simple = node.ptr_info.allowzero_token == null and + node.ptr_info.align_info == null and + node.ptr_info.volatile_token == null and + node.ptr_info.sentinel == null; + + if (simple) { + const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); + return addZIRUnOp(mod, scope, src, if (node.ptr_info.const_token == null) + .single_mut_ptr_type + else + .single_const_ptr_type, child_type); + } + + const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); + + var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{}; + kw_args.@"allowzero" = node.ptr_info.allowzero_token != null; + if (node.ptr_info.align_info) |some| { + kw_args.@"align" = try expr(mod, scope, .none, some.node); + if (some.bit_range) |bit_range| { + kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start); + kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end); + } + } + kw_args.@"const" = node.ptr_info.const_token != null; + kw_args.@"volatile" = node.ptr_info.volatile_token != null; + if (node.ptr_info.sentinel) |some| { + kw_args.sentinel = try expr(mod, scope, .{ .ty = child_type }, some); + } + + return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); +} + fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst { const tree = scope.tree(); const src = tree.token_locs[node.rtoken].start; diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index ef9351047b..25b3b171b4 100644 --- a/src-self-hosted/zir.zig +++ b/src-self-hosted/zir.zig @@ -192,6 +192,8 @@ pub const Inst = struct { single_const_ptr_type, /// Create a mutable pointer type based on the element type. `*T` single_mut_ptr_type, + /// Create a pointer type with attributes + ptr_type, /// Write a value to a pointer. For loading, see `deref`. store, /// String Literal. Makes an anonymous Decl and then takes a pointer to it. @@ -305,6 +307,7 @@ pub const Inst = struct { .fntype => FnType, .elemptr => ElemPtr, .condbr => CondBr, + .ptr_type => PtrType, }; } @@ -382,6 +385,7 @@ pub const Inst = struct { .optional_type, .unwrap_optional_safe, .unwrap_optional_unsafe, + .ptr_type, => false, .@"break", @@ -811,6 +815,24 @@ pub const Inst = struct { }, kw_args: struct {}, }; + + pub const PtrType = struct { + pub const base_tag = Tag.ptr_type; + base: Inst, + + positionals: struct { + child_type: *Inst, + }, + kw_args: struct { + @"allowzero": bool = false, + @"align": ?*Inst = null, + align_bit_start: ?*Inst = null, + align_bit_end: ?*Inst = null, + @"const": bool = true, + @"volatile": bool = false, + sentinel: ?*Inst = null, + }, + }; }; pub const ErrorMsg = struct { diff --git a/src-self-hosted/zir_sema.zig b/src-self-hosted/zir_sema.zig index 2fe9e5cfba..5047c61687 100644 --- a/src-self-hosted/zir_sema.zig +++ b/src-self-hosted/zir_sema.zig @@ -53,6 +53,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), .single_const_ptr_type => return analyzeInstSingleConstPtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?), .single_mut_ptr_type => return analyzeInstSingleMutPtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?), + .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?), .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?), .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?), .int => { @@ -1287,3 +1288,7 @@ fn analyzeInstSingleMutPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp const ty = try mod.singleMutPtrType(scope, inst.base.src, elem_type); return mod.constType(scope, inst.base.src, ty); } + +fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst { + return mod.fail(scope, inst.base.src, "TODO implement ptr_type", .{}); +}