From e85cd616ef6439fdb9e7ac118251bb7c2296e553 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Wed, 7 Apr 2021 14:55:11 +0200 Subject: [PATCH] stage2: implement builtin function hasDecl --- src/AstGen.zig | 12 +++++++++++- src/Sema.zig | 34 ++++++++++++++++++++++++++++++++++ src/zir.zig | 5 +++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index 364f76cc7a..20e52ea559 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1245,6 +1245,7 @@ fn blockExprStmts( .fn_type_var_args, .fn_type_cc, .fn_type_cc_var_args, + .has_decl, .int, .float, .float128, @@ -4159,6 +4160,16 @@ fn builtinCall( return rvalue(gz, scope, rl, .void_value, node); }, + .has_decl => { + const container_type = try typeExpr(gz, scope, params[0]); + const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); + const result = try gz.addPlNode(.has_decl, node, zir.Inst.Bin{ + .lhs = container_type, + .rhs = name, + }); + return rvalue(gz, scope, rl, result, node); + }, + .add_with_overflow, .align_cast, .align_of, @@ -4191,7 +4202,6 @@ fn builtinCall( .fence, .field_parent_ptr, .float_to_int, - .has_decl, .has_field, .int_to_float, .int_to_ptr, diff --git a/src/Sema.zig b/src/Sema.zig index d2abaaf091..b4b4798850 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -199,6 +199,7 @@ pub fn analyzeBody( .fn_type_cc => try sema.zirFnTypeCc(block, inst, false), .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true), .fn_type_var_args => try sema.zirFnType(block, inst, true), + .has_decl => try sema.zirHasDecl(block, inst), .import => try sema.zirImport(block, inst), .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), .int => try sema.zirInt(block, inst), @@ -3624,6 +3625,39 @@ fn validateSwitchNoRange( return sema.mod.failWithOwnedErrorMsg(&block.base, msg); } +fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { + const tracy = trace(@src()); + defer tracy.end(); + + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; + const src = inst_data.src(); + const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; + const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; + const container_type = try sema.resolveType(block, lhs_src, extra.lhs); + const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs); + + const maybe_scope = container_type.getContainerScope(); + if (maybe_scope == null) { + return sema.mod.fail( + &block.base, + src, + "expected container (struct, enum, or union), found '{}'", + .{container_type}, + ); + } + + const found = blk: { + for (maybe_scope.?.decls.items()) |kv| { + if (mem.eql(u8, mem.spanZ(kv.key.name), decl_name)) + break :blk true; + } + break :blk false; + }; + + return sema.mod.constBool(sema.arena, src, found); +} + fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { const tracy = trace(@src()); defer tracy.end(); diff --git a/src/zir.zig b/src/zir.zig index ff402a9ddb..40ad2b7844 100644 --- a/src/zir.zig +++ b/src/zir.zig @@ -364,6 +364,9 @@ pub const Inst = struct { fn_type_cc, /// Same as `fn_type_cc` but the function is variadic. fn_type_cc_var_args, + /// Determines whether a container has a declaration matching name. + /// Uses the `pl_node` union field. Payload is `Bin`. + has_decl, /// `@import(operand)`. /// Uses the `un_node` field. import, @@ -751,6 +754,7 @@ pub const Inst = struct { .fn_type_var_args, .fn_type_cc, .fn_type_cc_var_args, + .has_decl, .int, .float, .float128, @@ -1681,6 +1685,7 @@ const Writer = struct { .cmp_gt, .cmp_neq, .div, + .has_decl, .mod_rem, .shl, .shr,