AstGen: implement @extern builtin

This commit is contained in:
Andrew Kelley 2021-04-22 16:31:51 -07:00
parent 3d637e6dd2
commit 7c453b91b8
6 changed files with 66 additions and 0 deletions

View File

@ -6135,6 +6135,9 @@ fn builtinCall(
}
const ident_token = main_tokens[params[0]];
const decl_name = try gz.identAsString(ident_token);
// TODO look for local variables in scope matching `decl_name` and emit a compile
// error. Only top-level declarations can be exported. Until this is done, the
// compile error will end up being "use of undeclared identifier" in Sema.
const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]);
_ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
.decl_name = decl_name,
@ -6142,6 +6145,16 @@ fn builtinCall(
});
return rvalue(gz, scope, rl, .void_value, node);
},
.@"extern" => {
const type_inst = try typeExpr(gz, scope, params[0]);
const options = try comptimeExpr(gz, scope, .{ .ty = .extern_options_type }, params[1]);
const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
.lhs = type_inst,
.rhs = options,
});
return rvalue(gz, scope, rl, result, node);
},
.breakpoint => return simpleNoOpVoid(gz, scope, rl, node, .breakpoint),
.fence => return simpleNoOpVoid(gz, scope, rl, node, .fence),

View File

@ -39,6 +39,7 @@ pub const Tag = enum {
error_to_int,
err_set_cast,
@"export",
@"extern",
fence,
field,
field_parent_ptr,
@ -387,6 +388,13 @@ pub const list = list: {
.param_count = 2,
},
},
.{
"@extern",
.{
.tag = .@"extern",
.param_count = 2,
},
},
.{
"@fence",
.{

View File

@ -517,6 +517,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
.frame => return sema.zirFrame( block, extended),
.frame_address => return sema.zirFrameAddress( block, extended),
.alloc => return sema.zirAllocExtended( block, extended),
.builtin_extern => return sema.zirBuiltinExtern( block, extended),
.c_undef => return sema.zirCUndef( block, extended),
.c_include => return sema.zirCInclude( block, extended),
.c_define => return sema.zirCDefine( block, extended),
@ -5488,6 +5489,16 @@ fn zirWasmMemoryGrow(
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemoryGrow", .{});
}
fn zirBuiltinExtern(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinExtern", .{});
}
fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
if (sema.func == null) {
return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{});

View File

@ -1258,6 +1258,9 @@ pub const Inst = struct {
/// * 0b0X00 - 1=const, 0=var
/// * 0bX000 - is comptime
alloc,
/// The `@extern` builtin.
/// `operand` is payload index to `BinNode`.
builtin_extern,
/// `operand` is payload index to `UnNode`.
c_undef,
/// `operand` is payload index to `UnNode`.
@ -1353,6 +1356,7 @@ pub const Inst = struct {
reduce_op_type,
call_options_type,
export_options_type,
extern_options_type,
/// `undefined` (untyped)
undef,
@ -1580,6 +1584,10 @@ pub const Inst = struct {
.ty = Type.initTag(.type),
.val = Value.initTag(.export_options_type),
},
.extern_options_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.extern_options_type),
},
.undef = .{
.ty = Type.initTag(.@"undefined"),
@ -2598,6 +2606,7 @@ const Writer = struct {
.func,
.alloc,
.builtin_extern,
.c_undef,
.c_include,
.c_define,

View File

@ -100,6 +100,7 @@ pub const Type = extern union {
.@"struct",
.call_options,
.export_options,
.extern_options,
=> return .Struct,
.enum_full,
@ -618,6 +619,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> unreachable,
.array_u8,
@ -797,6 +799,7 @@ pub const Type = extern union {
.reduce_op => return writer.writeAll("std.builtin.ReduceOp"),
.call_options => return writer.writeAll("std.builtin.CallOptions"),
.export_options => return writer.writeAll("std.builtin.ExportOptions"),
.extern_options => return writer.writeAll("std.builtin.ExternOptions"),
.function => {
const payload = ty.castTag(.function).?.data;
try writer.writeAll("fn(");
@ -1012,6 +1015,7 @@ pub const Type = extern union {
.reduce_op => return Value.initTag(.reduce_op_type),
.call_options => return Value.initTag(.call_options_type),
.export_options => return Value.initTag(.export_options_type),
.extern_options => return Value.initTag(.extern_options_type),
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
else => return Value.Tag.ty.create(allocator, self),
@ -1070,6 +1074,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> true,
.@"struct" => {
@ -1181,6 +1186,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> return 1,
.fn_noreturn_no_args, // represents machine code; not a pointer
@ -1359,6 +1365,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> return 1,
.array_u8 => self.castTag(.array_u8).?.data,
@ -1623,6 +1630,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO at some point we gotta resolve builtin types"),
};
}
@ -2247,6 +2255,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> return null,
.@"struct" => {
@ -2413,6 +2422,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
@ -2436,6 +2446,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@ -2458,6 +2469,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@ -2502,6 +2514,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@ -2532,6 +2545,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@ -2563,6 +2577,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@ -2603,6 +2618,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
@ -2660,6 +2676,7 @@ pub const Type = extern union {
reduce_op,
call_options,
export_options,
extern_options,
@"null",
@"undefined",
fn_noreturn_no_args,
@ -2772,6 +2789,7 @@ pub const Type = extern union {
.reduce_op,
.call_options,
.export_options,
.extern_options,
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
.array_u8,

View File

@ -73,6 +73,7 @@ pub const Value = extern union {
reduce_op_type,
call_options_type,
export_options_type,
extern_options_type,
undef,
zero,
@ -187,6 +188,7 @@ pub const Value = extern union {
.reduce_op_type,
.call_options_type,
.export_options_type,
.extern_options_type,
=> @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
.int_big_positive,
@ -354,6 +356,7 @@ pub const Value = extern union {
.reduce_op_type,
.call_options_type,
.export_options_type,
.extern_options_type,
=> unreachable,
.ty => {
@ -510,6 +513,7 @@ pub const Value = extern union {
.reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),
.call_options_type => return out_stream.writeAll("std.builtin.CallOptions"),
.export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"),
.extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"),
.abi_align_default => return out_stream.writeAll("(default ABI alignment)"),
.empty_struct_value => return out_stream.writeAll("struct {}{}"),
@ -640,6 +644,7 @@ pub const Value = extern union {
.reduce_op_type => Type.initTag(.reduce_op),
.call_options_type => Type.initTag(.call_options),
.export_options_type => Type.initTag(.export_options),
.extern_options_type => Type.initTag(.extern_options),
.int_type => {
const payload = self.castTag(.int_type).?.data;
@ -1187,6 +1192,7 @@ pub const Value = extern union {
.reduce_op_type,
.call_options_type,
.export_options_type,
.extern_options_type,
=> @panic("TODO this hash function looks pretty broken. audit it"),
}
return hasher.final();
@ -1343,6 +1349,7 @@ pub const Value = extern union {
.reduce_op_type,
.call_options_type,
.export_options_type,
.extern_options_type,
=> true,
.zero,