authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-29 19:44:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-29 19:44:51-07:00
log86d564eed8b9eacd0447598dd364ab04c5b1b04d
treed4fff51821459dd9ae181a31c667cac1bd2b3bbc
parentba9b9cb38dbd66c7a600606c5599c80b115e0f85

AstGen: implement extern variables


4 files changed, 139 insertions(+), 16 deletions(-)

src/AstGen.zig+13-7
......@@ -2961,7 +2961,7 @@ fn globalVarDecl(
29612961
29622962 assert(var_decl.comptime_token == null); // handled by parser
29632963
2964 const var_inst: Zir.Inst.Index = if (var_decl.ast.init_node != 0) vi: {
2964 if (var_decl.ast.init_node != 0) {
29652965 if (is_extern) {
29662966 return astgen.failNode(
29672967 var_decl.ast.init_node,
......@@ -2989,19 +2989,25 @@ fn globalVarDecl(
29892989 // We do this at the end so that the instruction index marks the end
29902990 // range of a top level declaration.
29912991 _ = try block_scope.addBreak(.break_inline, block_inst, init_inst);
2992 try block_scope.setBlockBody(block_inst);
2993 break :vi block_inst;
29942992 } else if (!is_extern) {
29952993 return astgen.failNode(node, "variables must be initialized", .{});
29962994 } else if (var_decl.ast.type_node != 0) {
29972995 // Extern variable which has an explicit type.
2998
29992996 const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node);
30002997
3001 return astgen.failNode(node, "TODO AstGen extern global variable", .{});
2998 const var_inst = try block_scope.addVar(.{
2999 .var_type = type_inst,
3000 .lib_name = lib_name,
3001 .align_inst = .none, // passed in the decls data
3002 .init = .none,
3003 .is_extern = true,
3004 });
3005
3006 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
30023007 } else {
30033008 return astgen.failNode(node, "unable to infer variable type", .{});
3004 };
3009 }
3010 try block_scope.setBlockBody(block_inst);
30053011
30063012 const name_token = var_decl.ast.mut_token + 1;
30073013 const name_str_index = try gz.identAsString(name_token);
......@@ -3013,7 +3019,7 @@ fn globalVarDecl(
30133019 wip_decls.payload.appendSliceAssumeCapacity(&casted);
30143020 }
30153021 wip_decls.payload.appendAssumeCapacity(name_str_index);
3016 wip_decls.payload.appendAssumeCapacity(var_inst);
3022 wip_decls.payload.appendAssumeCapacity(block_inst);
30173023 if (align_inst != .none) {
30183024 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
30193025 }
src/Module.zig+51
......@@ -1462,6 +1462,57 @@ pub const Scope = struct {
14621462 }
14631463 }
14641464
1465 pub fn addVar(gz: *GenZir, args: struct {
1466 align_inst: Zir.Inst.Ref,
1467 lib_name: u32,
1468 var_type: Zir.Inst.Ref,
1469 init: Zir.Inst.Ref,
1470 is_extern: bool,
1471 }) !Zir.Inst.Ref {
1472 const astgen = gz.astgen;
1473 const gpa = astgen.gpa;
1474
1475 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1476 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1477
1478 try astgen.extra.ensureUnusedCapacity(
1479 gpa,
1480 @typeInfo(Zir.Inst.ExtendedVar).Struct.fields.len +
1481 @boolToInt(args.lib_name != 0) +
1482 @boolToInt(args.align_inst != .none) +
1483 @boolToInt(args.init != .none),
1484 );
1485 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
1486 .var_type = args.var_type,
1487 });
1488 if (args.lib_name != 0) {
1489 astgen.extra.appendAssumeCapacity(args.lib_name);
1490 }
1491 if (args.align_inst != .none) {
1492 astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
1493 }
1494 if (args.init != .none) {
1495 astgen.extra.appendAssumeCapacity(@enumToInt(args.init));
1496 }
1497
1498 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1499 astgen.instructions.appendAssumeCapacity(.{
1500 .tag = .extended,
1501 .data = .{ .extended = .{
1502 .opcode = .variable,
1503 .small = @bitCast(u16, Zir.Inst.ExtendedVar.Small{
1504 .has_lib_name = args.lib_name != 0,
1505 .has_align = args.align_inst != .none,
1506 .has_init = args.init != .none,
1507 .is_extern = args.is_extern,
1508 }),
1509 .operand = payload_index,
1510 } },
1511 });
1512 gz.instructions.appendAssumeCapacity(new_index);
1513 return gz.indexToRef(new_index);
1514 }
1515
14651516 pub fn addCall(
14661517 gz: *GenZir,
14671518 tag: Zir.Inst.Tag,
src/Sema.zig+12
......@@ -479,6 +479,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
479479 switch (extended.opcode) {
480480 // zig fmt: off
481481 .func => return sema.zirFuncExtended( block, extended),
482 .variable => return sema.zirVarExtended( block, extended),
482483 .ret_ptr => return sema.zirRetPtr( block, extended),
483484 .ret_type => return sema.zirRetType( block, extended),
484485 .this => return sema.zirThis( block, extended),
......@@ -5427,6 +5428,17 @@ fn zirAwait(
54275428 return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{});
54285429}
54295430
5431fn zirVarExtended(
5432 sema: *Sema,
5433 block: *Scope.Block,
5434 extended: Zir.Inst.Extended.InstData,
5435) InnerError!*Inst {
5436 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
5437 const src = sema.src;
5438
5439 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirVarExtended", .{});
5440}
5441
54305442fn zirFuncExtended(
54315443 sema: *Sema,
54325444 block: *Scope.Block,
src/Zir.zig+63-9
......@@ -1496,6 +1496,10 @@ pub const Inst = struct {
14961496 /// `operand` is payload index to `ExtendedFunc`.
14971497 /// `small` is `ExtendedFunc.Small`.
14981498 func,
1499 /// Declares a global variable.
1500 /// `operand` is payload index to `ExtendedVar`.
1501 /// `small` is `ExtendedVar.Small`.
1502 variable,
14991503 /// Obtains a pointer to the return value.
15001504 /// `operand` is `src_node: i32`.
15011505 ret_ptr,
......@@ -2209,6 +2213,23 @@ pub const Inst = struct {
22092213 };
22102214 };
22112215
2216 /// Trailing:
2217 /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
2218 /// 1. align: Ref, // if has_align is set
2219 /// 2. init: Ref // if has_init is set
2220 /// The source node is obtained from the containing `block_inline`.
2221 pub const ExtendedVar = struct {
2222 var_type: Ref,
2223
2224 pub const Small = packed struct {
2225 has_lib_name: bool,
2226 has_align: bool,
2227 has_init: bool,
2228 is_extern: bool,
2229 _: u12 = undefined,
2230 };
2231 };
2232
22122233 /// Trailing:
22132234 /// 0. param_type: Ref // for each param_types_len
22142235 /// - `none` indicates that the param type is `anytype`.
......@@ -3010,6 +3031,7 @@ const Writer = struct {
30103031
30113032 .@"asm" => try self.writeAsm(stream, extended),
30123033 .func => try self.writeFuncExtended(stream, extended),
3034 .variable => try self.writeVarExtended(stream, extended),
30133035
30143036 .compile_log,
30153037 .typeof_peer,
......@@ -4015,6 +4037,34 @@ const Writer = struct {
40154037 );
40164038 }
40174039
4040 fn writeVarExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
4041 const extra = self.code.extraData(Inst.ExtendedVar, extended.operand);
4042 const small = @bitCast(Inst.ExtendedVar.Small, extended.small);
4043
4044 try self.writeInstRef(stream, extra.data.var_type);
4045
4046 var extra_index: usize = extra.end;
4047 if (small.has_lib_name) {
4048 const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
4049 extra_index += 1;
4050 try stream.print(", lib_name=\"{}\"", .{std.zig.fmtEscapes(lib_name)});
4051 }
4052 const align_inst: Inst.Ref = if (!small.has_align) .none else blk: {
4053 const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
4054 extra_index += 1;
4055 break :blk align_inst;
4056 };
4057 const init_inst: Inst.Ref = if (!small.has_init) .none else blk: {
4058 const init_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
4059 extra_index += 1;
4060 break :blk init_inst;
4061 };
4062 try self.writeFlag(stream, ", is_extern", small.is_extern);
4063 try self.writeOptionalInstRef(stream, ", align=", align_inst);
4064 try self.writeOptionalInstRef(stream, ", init=", init_inst);
4065 try stream.writeAll("))");
4066 }
4067
40184068 fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
40194069 const inst_data = self.code.instructions.items(.data)[inst].bool_br;
40204070 const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
......@@ -4078,15 +4128,19 @@ const Writer = struct {
40784128 try self.writeFlag(stream, ", vargs", var_args);
40794129 try self.writeFlag(stream, ", inferror", inferred_error_set);
40804130
4081 try stream.writeAll(", {\n");
4082 self.indent += 2;
4083 const prev_param_count = self.param_count;
4084 self.param_count = param_types.len;
4085 try self.writeBody(stream, body);
4086 self.param_count = prev_param_count;
4087 self.indent -= 2;
4088 try stream.writeByteNTimes(' ', self.indent);
4089 try stream.writeAll("}) ");
4131 if (body.len == 0) {
4132 try stream.writeAll(", {}) ");
4133 } else {
4134 try stream.writeAll(", {\n");
4135 self.indent += 2;
4136 const prev_param_count = self.param_count;
4137 self.param_count = param_types.len;
4138 try self.writeBody(stream, body);
4139 self.param_count = prev_param_count;
4140 self.indent -= 2;
4141 try stream.writeByteNTimes(' ', self.indent);
4142 try stream.writeAll("}) ");
4143 }
40904144 try self.writeSrc(stream, src);
40914145 }
40924146