mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
AstGen: implement extern variables
This commit is contained in:
parent
ba9b9cb38d
commit
86d564eed8
@ -2961,7 +2961,7 @@ fn globalVarDecl(
|
||||
|
||||
assert(var_decl.comptime_token == null); // handled by parser
|
||||
|
||||
const var_inst: Zir.Inst.Index = if (var_decl.ast.init_node != 0) vi: {
|
||||
if (var_decl.ast.init_node != 0) {
|
||||
if (is_extern) {
|
||||
return astgen.failNode(
|
||||
var_decl.ast.init_node,
|
||||
@ -2989,19 +2989,25 @@ fn globalVarDecl(
|
||||
// We do this at the end so that the instruction index marks the end
|
||||
// range of a top level declaration.
|
||||
_ = try block_scope.addBreak(.break_inline, block_inst, init_inst);
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
break :vi block_inst;
|
||||
} else if (!is_extern) {
|
||||
return astgen.failNode(node, "variables must be initialized", .{});
|
||||
} else if (var_decl.ast.type_node != 0) {
|
||||
// Extern variable which has an explicit type.
|
||||
|
||||
const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node);
|
||||
|
||||
return astgen.failNode(node, "TODO AstGen extern global variable", .{});
|
||||
const var_inst = try block_scope.addVar(.{
|
||||
.var_type = type_inst,
|
||||
.lib_name = lib_name,
|
||||
.align_inst = .none, // passed in the decls data
|
||||
.init = .none,
|
||||
.is_extern = true,
|
||||
});
|
||||
|
||||
_ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
|
||||
} else {
|
||||
return astgen.failNode(node, "unable to infer variable type", .{});
|
||||
};
|
||||
}
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
|
||||
const name_token = var_decl.ast.mut_token + 1;
|
||||
const name_str_index = try gz.identAsString(name_token);
|
||||
@ -3013,7 +3019,7 @@ fn globalVarDecl(
|
||||
wip_decls.payload.appendSliceAssumeCapacity(&casted);
|
||||
}
|
||||
wip_decls.payload.appendAssumeCapacity(name_str_index);
|
||||
wip_decls.payload.appendAssumeCapacity(var_inst);
|
||||
wip_decls.payload.appendAssumeCapacity(block_inst);
|
||||
if (align_inst != .none) {
|
||||
wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
|
||||
}
|
||||
|
||||
@ -1462,6 +1462,57 @@ pub const Scope = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addVar(gz: *GenZir, args: struct {
|
||||
align_inst: Zir.Inst.Ref,
|
||||
lib_name: u32,
|
||||
var_type: Zir.Inst.Ref,
|
||||
init: Zir.Inst.Ref,
|
||||
is_extern: bool,
|
||||
}) !Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
try gz.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
try astgen.extra.ensureUnusedCapacity(
|
||||
gpa,
|
||||
@typeInfo(Zir.Inst.ExtendedVar).Struct.fields.len +
|
||||
@boolToInt(args.lib_name != 0) +
|
||||
@boolToInt(args.align_inst != .none) +
|
||||
@boolToInt(args.init != .none),
|
||||
);
|
||||
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedVar{
|
||||
.var_type = args.var_type,
|
||||
});
|
||||
if (args.lib_name != 0) {
|
||||
astgen.extra.appendAssumeCapacity(args.lib_name);
|
||||
}
|
||||
if (args.align_inst != .none) {
|
||||
astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst));
|
||||
}
|
||||
if (args.init != .none) {
|
||||
astgen.extra.appendAssumeCapacity(@enumToInt(args.init));
|
||||
}
|
||||
|
||||
const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
|
||||
astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = .extended,
|
||||
.data = .{ .extended = .{
|
||||
.opcode = .variable,
|
||||
.small = @bitCast(u16, Zir.Inst.ExtendedVar.Small{
|
||||
.has_lib_name = args.lib_name != 0,
|
||||
.has_align = args.align_inst != .none,
|
||||
.has_init = args.init != .none,
|
||||
.is_extern = args.is_extern,
|
||||
}),
|
||||
.operand = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return gz.indexToRef(new_index);
|
||||
}
|
||||
|
||||
pub fn addCall(
|
||||
gz: *GenZir,
|
||||
tag: Zir.Inst.Tag,
|
||||
|
||||
12
src/Sema.zig
12
src/Sema.zig
@ -479,6 +479,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
|
||||
switch (extended.opcode) {
|
||||
// zig fmt: off
|
||||
.func => return sema.zirFuncExtended( block, extended),
|
||||
.variable => return sema.zirVarExtended( block, extended),
|
||||
.ret_ptr => return sema.zirRetPtr( block, extended),
|
||||
.ret_type => return sema.zirRetType( block, extended),
|
||||
.this => return sema.zirThis( block, extended),
|
||||
@ -5427,6 +5428,17 @@ fn zirAwait(
|
||||
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{});
|
||||
}
|
||||
|
||||
fn zirVarExtended(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
extended: Zir.Inst.Extended.InstData,
|
||||
) InnerError!*Inst {
|
||||
const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
|
||||
const src = sema.src;
|
||||
|
||||
return sema.mod.fail(&block.base, src, "TODO implement Sema.zirVarExtended", .{});
|
||||
}
|
||||
|
||||
fn zirFuncExtended(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
|
||||
72
src/Zir.zig
72
src/Zir.zig
@ -1496,6 +1496,10 @@ pub const Inst = struct {
|
||||
/// `operand` is payload index to `ExtendedFunc`.
|
||||
/// `small` is `ExtendedFunc.Small`.
|
||||
func,
|
||||
/// Declares a global variable.
|
||||
/// `operand` is payload index to `ExtendedVar`.
|
||||
/// `small` is `ExtendedVar.Small`.
|
||||
variable,
|
||||
/// Obtains a pointer to the return value.
|
||||
/// `operand` is `src_node: i32`.
|
||||
ret_ptr,
|
||||
@ -2209,6 +2213,23 @@ pub const Inst = struct {
|
||||
};
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
|
||||
/// 1. align: Ref, // if has_align is set
|
||||
/// 2. init: Ref // if has_init is set
|
||||
/// The source node is obtained from the containing `block_inline`.
|
||||
pub const ExtendedVar = struct {
|
||||
var_type: Ref,
|
||||
|
||||
pub const Small = packed struct {
|
||||
has_lib_name: bool,
|
||||
has_align: bool,
|
||||
has_init: bool,
|
||||
is_extern: bool,
|
||||
_: u12 = undefined,
|
||||
};
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. param_type: Ref // for each param_types_len
|
||||
/// - `none` indicates that the param type is `anytype`.
|
||||
@ -3010,6 +3031,7 @@ const Writer = struct {
|
||||
|
||||
.@"asm" => try self.writeAsm(stream, extended),
|
||||
.func => try self.writeFuncExtended(stream, extended),
|
||||
.variable => try self.writeVarExtended(stream, extended),
|
||||
|
||||
.compile_log,
|
||||
.typeof_peer,
|
||||
@ -4015,6 +4037,34 @@ const Writer = struct {
|
||||
);
|
||||
}
|
||||
|
||||
fn writeVarExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
|
||||
const extra = self.code.extraData(Inst.ExtendedVar, extended.operand);
|
||||
const small = @bitCast(Inst.ExtendedVar.Small, extended.small);
|
||||
|
||||
try self.writeInstRef(stream, extra.data.var_type);
|
||||
|
||||
var extra_index: usize = extra.end;
|
||||
if (small.has_lib_name) {
|
||||
const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
try stream.print(", lib_name=\"{}\"", .{std.zig.fmtEscapes(lib_name)});
|
||||
}
|
||||
const align_inst: Inst.Ref = if (!small.has_align) .none else blk: {
|
||||
const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
break :blk align_inst;
|
||||
};
|
||||
const init_inst: Inst.Ref = if (!small.has_init) .none else blk: {
|
||||
const init_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
break :blk init_inst;
|
||||
};
|
||||
try self.writeFlag(stream, ", is_extern", small.is_extern);
|
||||
try self.writeOptionalInstRef(stream, ", align=", align_inst);
|
||||
try self.writeOptionalInstRef(stream, ", init=", init_inst);
|
||||
try stream.writeAll("))");
|
||||
}
|
||||
|
||||
fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].bool_br;
|
||||
const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
|
||||
@ -4078,15 +4128,19 @@ const Writer = struct {
|
||||
try self.writeFlag(stream, ", vargs", var_args);
|
||||
try self.writeFlag(stream, ", inferror", inferred_error_set);
|
||||
|
||||
try stream.writeAll(", {\n");
|
||||
self.indent += 2;
|
||||
const prev_param_count = self.param_count;
|
||||
self.param_count = param_types.len;
|
||||
try self.writeBody(stream, body);
|
||||
self.param_count = prev_param_count;
|
||||
self.indent -= 2;
|
||||
try stream.writeByteNTimes(' ', self.indent);
|
||||
try stream.writeAll("}) ");
|
||||
if (body.len == 0) {
|
||||
try stream.writeAll(", {}) ");
|
||||
} else {
|
||||
try stream.writeAll(", {\n");
|
||||
self.indent += 2;
|
||||
const prev_param_count = self.param_count;
|
||||
self.param_count = param_types.len;
|
||||
try self.writeBody(stream, body);
|
||||
self.param_count = prev_param_count;
|
||||
self.indent -= 2;
|
||||
try stream.writeByteNTimes(' ', self.indent);
|
||||
try stream.writeAll("}) ");
|
||||
}
|
||||
try self.writeSrc(stream, src);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user