| author | |
| committer | |
| log | 86d564eed8b9eacd0447598dd364ab04c5b1b04d |
| tree | d4fff51821459dd9ae181a31c667cac1bd2b3bbc |
| parent | ba9b9cb38dbd66c7a600606c5599c80b115e0f85 |
4 files changed, 139 insertions(+), 16 deletions(-)
src/AstGen.zig+13-7| ... | @@ -2961,7 +2961,7 @@ fn globalVarDecl( | ... | @@ -2961,7 +2961,7 @@ fn globalVarDecl( |
| 2961 | 2961 | ||
| 2962 | assert(var_decl.comptime_token == null); // handled by parser | 2962 | assert(var_decl.comptime_token == null); // handled by parser |
| 2963 | 2963 | ||
| 2964 | const var_inst: Zir.Inst.Index = if (var_decl.ast.init_node != 0) vi: { | 2964 | if (var_decl.ast.init_node != 0) { |
| 2965 | if (is_extern) { | 2965 | if (is_extern) { |
| 2966 | return astgen.failNode( | 2966 | return astgen.failNode( |
| 2967 | var_decl.ast.init_node, | 2967 | var_decl.ast.init_node, |
| ... | @@ -2989,19 +2989,25 @@ fn globalVarDecl( | ... | @@ -2989,19 +2989,25 @@ fn globalVarDecl( |
| 2989 | // We do this at the end so that the instruction index marks the end | 2989 | // We do this at the end so that the instruction index marks the end |
| 2990 | // range of a top level declaration. | 2990 | // range of a top level declaration. |
| 2991 | _ = try block_scope.addBreak(.break_inline, block_inst, init_inst); | 2991 | _ = try block_scope.addBreak(.break_inline, block_inst, init_inst); |
| 2992 | try block_scope.setBlockBody(block_inst); | ||
| 2993 | break :vi block_inst; | ||
| 2994 | } else if (!is_extern) { | 2992 | } else if (!is_extern) { |
| 2995 | return astgen.failNode(node, "variables must be initialized", .{}); | 2993 | return astgen.failNode(node, "variables must be initialized", .{}); |
| 2996 | } else if (var_decl.ast.type_node != 0) { | 2994 | } else if (var_decl.ast.type_node != 0) { |
| 2997 | // Extern variable which has an explicit type. | 2995 | // Extern variable which has an explicit type. |
| 2998 | |||
| 2999 | const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node); | 2996 | const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node); |
| 3000 | 2997 | ||
| 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); | ||
| 3002 | } else { | 3007 | } else { |
| 3003 | return astgen.failNode(node, "unable to infer variable type", .{}); | 3008 | return astgen.failNode(node, "unable to infer variable type", .{}); |
| 3004 | }; | 3009 | } |
| 3010 | try block_scope.setBlockBody(block_inst); | ||
| 3005 | 3011 | ||
| 3006 | const name_token = var_decl.ast.mut_token + 1; | 3012 | const name_token = var_decl.ast.mut_token + 1; |
| 3007 | const name_str_index = try gz.identAsString(name_token); | 3013 | const name_str_index = try gz.identAsString(name_token); |
| ... | @@ -3013,7 +3019,7 @@ fn globalVarDecl( | ... | @@ -3013,7 +3019,7 @@ fn globalVarDecl( |
| 3013 | wip_decls.payload.appendSliceAssumeCapacity(&casted); | 3019 | wip_decls.payload.appendSliceAssumeCapacity(&casted); |
| 3014 | } | 3020 | } |
| 3015 | wip_decls.payload.appendAssumeCapacity(name_str_index); | 3021 | wip_decls.payload.appendAssumeCapacity(name_str_index); |
| 3016 | wip_decls.payload.appendAssumeCapacity(var_inst); | 3022 | wip_decls.payload.appendAssumeCapacity(block_inst); |
| 3017 | if (align_inst != .none) { | 3023 | if (align_inst != .none) { |
| 3018 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); | 3024 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3019 | } | 3025 | } |
src/Module.zig+51| ... | @@ -1462,6 +1462,57 @@ pub const Scope = struct { | ... | @@ -1462,6 +1462,57 @@ pub const Scope = struct { |
| 1462 | } | 1462 | } |
| 1463 | } | 1463 | } |
| 1464 | 1464 | ||
| 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 | |||
| 1465 | pub fn addCall( | 1516 | pub fn addCall( |
| 1466 | gz: *GenZir, | 1517 | gz: *GenZir, |
| 1467 | tag: Zir.Inst.Tag, | 1518 | tag: Zir.Inst.Tag, |
src/Sema.zig+12| ... | @@ -479,6 +479,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro | ... | @@ -479,6 +479,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro |
| 479 | switch (extended.opcode) { | 479 | switch (extended.opcode) { |
| 480 | // zig fmt: off | 480 | // zig fmt: off |
| 481 | .func => return sema.zirFuncExtended( block, extended), | 481 | .func => return sema.zirFuncExtended( block, extended), |
| 482 | .variable => return sema.zirVarExtended( block, extended), | ||
| 482 | .ret_ptr => return sema.zirRetPtr( block, extended), | 483 | .ret_ptr => return sema.zirRetPtr( block, extended), |
| 483 | .ret_type => return sema.zirRetType( block, extended), | 484 | .ret_type => return sema.zirRetType( block, extended), |
| 484 | .this => return sema.zirThis( block, extended), | 485 | .this => return sema.zirThis( block, extended), |
| ... | @@ -5427,6 +5428,17 @@ fn zirAwait( | ... | @@ -5427,6 +5428,17 @@ fn zirAwait( |
| 5427 | return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{}); | 5428 | return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{}); |
| 5428 | } | 5429 | } |
| 5429 | 5430 | ||
| 5431 | fn 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 | |||
| 5430 | fn zirFuncExtended( | 5442 | fn zirFuncExtended( |
| 5431 | sema: *Sema, | 5443 | sema: *Sema, |
| 5432 | block: *Scope.Block, | 5444 | block: *Scope.Block, |
src/Zir.zig+63-9| ... | @@ -1496,6 +1496,10 @@ pub const Inst = struct { | ... | @@ -1496,6 +1496,10 @@ pub const Inst = struct { |
| 1496 | /// `operand` is payload index to `ExtendedFunc`. | 1496 | /// `operand` is payload index to `ExtendedFunc`. |
| 1497 | /// `small` is `ExtendedFunc.Small`. | 1497 | /// `small` is `ExtendedFunc.Small`. |
| 1498 | func, | 1498 | func, |
| 1499 | /// Declares a global variable. | ||
| 1500 | /// `operand` is payload index to `ExtendedVar`. | ||
| 1501 | /// `small` is `ExtendedVar.Small`. | ||
| 1502 | variable, | ||
| 1499 | /// Obtains a pointer to the return value. | 1503 | /// Obtains a pointer to the return value. |
| 1500 | /// `operand` is `src_node: i32`. | 1504 | /// `operand` is `src_node: i32`. |
| 1501 | ret_ptr, | 1505 | ret_ptr, |
| ... | @@ -2209,6 +2213,23 @@ pub const Inst = struct { | ... | @@ -2209,6 +2213,23 @@ pub const Inst = struct { |
| 2209 | }; | 2213 | }; |
| 2210 | }; | 2214 | }; |
| 2211 | 2215 | ||
| 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 | |||
| 2212 | /// Trailing: | 2233 | /// Trailing: |
| 2213 | /// 0. param_type: Ref // for each param_types_len | 2234 | /// 0. param_type: Ref // for each param_types_len |
| 2214 | /// - `none` indicates that the param type is `anytype`. | 2235 | /// - `none` indicates that the param type is `anytype`. |
| ... | @@ -3010,6 +3031,7 @@ const Writer = struct { | ... | @@ -3010,6 +3031,7 @@ const Writer = struct { |
| 3010 | 3031 | ||
| 3011 | .@"asm" => try self.writeAsm(stream, extended), | 3032 | .@"asm" => try self.writeAsm(stream, extended), |
| 3012 | .func => try self.writeFuncExtended(stream, extended), | 3033 | .func => try self.writeFuncExtended(stream, extended), |
| 3034 | .variable => try self.writeVarExtended(stream, extended), | ||
| 3013 | 3035 | ||
| 3014 | .compile_log, | 3036 | .compile_log, |
| 3015 | .typeof_peer, | 3037 | .typeof_peer, |
| ... | @@ -4015,6 +4037,34 @@ const Writer = struct { | ... | @@ -4015,6 +4037,34 @@ const Writer = struct { |
| 4015 | ); | 4037 | ); |
| 4016 | } | 4038 | } |
| 4017 | 4039 | ||
| 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 | |||
| 4018 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 4068 | fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 4019 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; | 4069 | const inst_data = self.code.instructions.items(.data)[inst].bool_br; |
| 4020 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); | 4070 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); |
| ... | @@ -4078,15 +4128,19 @@ const Writer = struct { | ... | @@ -4078,15 +4128,19 @@ const Writer = struct { |
| 4078 | try self.writeFlag(stream, ", vargs", var_args); | 4128 | try self.writeFlag(stream, ", vargs", var_args); |
| 4079 | try self.writeFlag(stream, ", inferror", inferred_error_set); | 4129 | try self.writeFlag(stream, ", inferror", inferred_error_set); |
| 4080 | 4130 | ||
| 4081 | try stream.writeAll(", {\n"); | 4131 | if (body.len == 0) { |
| 4082 | self.indent += 2; | 4132 | try stream.writeAll(", {}) "); |
| 4083 | const prev_param_count = self.param_count; | 4133 | } else { |
| 4084 | self.param_count = param_types.len; | 4134 | try stream.writeAll(", {\n"); |
| 4085 | try self.writeBody(stream, body); | 4135 | self.indent += 2; |
| 4086 | self.param_count = prev_param_count; | 4136 | const prev_param_count = self.param_count; |
| 4087 | self.indent -= 2; | 4137 | self.param_count = param_types.len; |
| 4088 | try stream.writeByteNTimes(' ', self.indent); | 4138 | try self.writeBody(stream, body); |
| 4089 | try stream.writeAll("}) "); | 4139 | self.param_count = prev_param_count; |
| 4140 | self.indent -= 2; | ||
| 4141 | try stream.writeByteNTimes(' ', self.indent); | ||
| 4142 | try stream.writeAll("}) "); | ||
| 4143 | } | ||
| 4090 | try self.writeSrc(stream, src); | 4144 | try self.writeSrc(stream, src); |
| 4091 | } | 4145 | } |
| 4092 | 4146 |