self hosted compiler: use enum literals

This commit is contained in:
Vexu 2019-11-07 08:31:00 +02:00
parent 7000316113
commit c6076a1360
No known key found for this signature in database
GPG Key ID: 5AEABFCAFF5CD8D6
17 changed files with 608 additions and 620 deletions

View File

@ -119,9 +119,9 @@ pub const Args = struct {
// MergeN creation disallows 0 length flag entry (doesn't make sense) // MergeN creation disallows 0 length flag entry (doesn't make sense)
switch (flag_args) { switch (flag_args) {
FlagArg.None => unreachable, .None => unreachable,
FlagArg.Single => |inner| try prev.append(inner), .Single => |inner| try prev.append(inner),
FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()), .Many => |inner| try prev.appendSlice(inner.toSliceConst()),
} }
_ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev }); _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
@ -158,7 +158,7 @@ pub const Args = struct {
pub fn single(self: *Args, name: []const u8) ?[]const u8 { pub fn single(self: *Args, name: []const u8) ?[]const u8 {
if (self.flags.get(name)) |entry| { if (self.flags.get(name)) |entry| {
switch (entry.value) { switch (entry.value) {
FlagArg.Single => |inner| { .Single => |inner| {
return inner; return inner;
}, },
else => @panic("attempted to retrieve flag with wrong type"), else => @panic("attempted to retrieve flag with wrong type"),
@ -172,7 +172,7 @@ pub const Args = struct {
pub fn many(self: *Args, name: []const u8) []const []const u8 { pub fn many(self: *Args, name: []const u8) []const []const u8 {
if (self.flags.get(name)) |entry| { if (self.flags.get(name)) |entry| {
switch (entry.value) { switch (entry.value) {
FlagArg.Many => |inner| { .Many => |inner| {
return inner.toSliceConst(); return inner.toSliceConst();
}, },
else => @panic("attempted to retrieve flag with wrong type"), else => @panic("attempted to retrieve flag with wrong type"),

View File

@ -19,56 +19,56 @@ pub const CInt = struct {
pub const list = [_]CInt{ pub const list = [_]CInt{
CInt{ CInt{
.id = Id.Short, .id = .Short,
.zig_name = "c_short", .zig_name = "c_short",
.c_name = "short", .c_name = "short",
.is_signed = true, .is_signed = true,
}, },
CInt{ CInt{
.id = Id.UShort, .id = .UShort,
.zig_name = "c_ushort", .zig_name = "c_ushort",
.c_name = "unsigned short", .c_name = "unsigned short",
.is_signed = false, .is_signed = false,
}, },
CInt{ CInt{
.id = Id.Int, .id = .Int,
.zig_name = "c_int", .zig_name = "c_int",
.c_name = "int", .c_name = "int",
.is_signed = true, .is_signed = true,
}, },
CInt{ CInt{
.id = Id.UInt, .id = .UInt,
.zig_name = "c_uint", .zig_name = "c_uint",
.c_name = "unsigned int", .c_name = "unsigned int",
.is_signed = false, .is_signed = false,
}, },
CInt{ CInt{
.id = Id.Long, .id = .Long,
.zig_name = "c_long", .zig_name = "c_long",
.c_name = "long", .c_name = "long",
.is_signed = true, .is_signed = true,
}, },
CInt{ CInt{
.id = Id.ULong, .id = .ULong,
.zig_name = "c_ulong", .zig_name = "c_ulong",
.c_name = "unsigned long", .c_name = "unsigned long",
.is_signed = false, .is_signed = false,
}, },
CInt{ CInt{
.id = Id.LongLong, .id = .LongLong,
.zig_name = "c_longlong", .zig_name = "c_longlong",
.c_name = "long long", .c_name = "long long",
.is_signed = true, .is_signed = true,
}, },
CInt{ CInt{
.id = Id.ULongLong, .id = .ULongLong,
.zig_name = "c_ulonglong", .zig_name = "c_ulonglong",
.c_name = "unsigned long long", .c_name = "unsigned long long",
.is_signed = false, .is_signed = false,
}, },
}; };
pub fn sizeInBits(id: CInt.Id, self: Target) u32 { pub fn sizeInBits(id: Id, self: Target) u32 {
const arch = self.getArch(); const arch = self.getArch();
switch (self.getOs()) { switch (self.getOs()) {
.freestanding => switch (self.getArch()) { .freestanding => switch (self.getArch()) {

View File

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
const llvm = @import("llvm.zig"); const llvm = @import("llvm.zig");
const c = @import("c.zig"); const c = @import("c.zig");
@ -31,7 +30,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
llvm.SetTarget(module, comp.llvm_triple.ptr()); llvm.SetTarget(module, comp.llvm_triple.ptr());
llvm.SetDataLayout(module, comp.target_layout_str); llvm.SetDataLayout(module, comp.target_layout_str);
if (comp.target.getObjectFormat() == builtin.ObjectFormat.coff) { if (comp.target.getObjectFormat() == .coff) {
llvm.AddModuleCodeViewFlag(module); llvm.AddModuleCodeViewFlag(module);
} else { } else {
llvm.AddModuleDebugInfoFlag(module); llvm.AddModuleDebugInfoFlag(module);
@ -59,7 +58,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
comp.name.ptr(), comp.name.ptr(),
comp.root_package.root_src_dir.ptr(), comp.root_package.root_src_dir.ptr(),
) orelse return error.OutOfMemory; ) orelse return error.OutOfMemory;
const is_optimized = comp.build_mode != builtin.Mode.Debug; const is_optimized = comp.build_mode != .Debug;
const compile_unit = llvm.CreateCompileUnit( const compile_unit = llvm.CreateCompileUnit(
dibuilder, dibuilder,
DW.LANG_C99, DW.LANG_C99,
@ -105,8 +104,8 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types
const is_small = comp.build_mode == builtin.Mode.ReleaseSmall; const is_small = comp.build_mode == .ReleaseSmall;
const is_debug = comp.build_mode == builtin.Mode.Debug; const is_debug = comp.build_mode == .Debug;
var err_msg: [*]u8 = undefined; var err_msg: [*]u8 = undefined;
// TODO integrate this with evented I/O // TODO integrate this with evented I/O
@ -114,7 +113,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
comp.target_machine, comp.target_machine,
module, module,
output_path.ptr(), output_path.ptr(),
llvm.EmitBinary, .EmitBinary,
&err_msg, &err_msg,
is_debug, is_debug,
is_small, is_small,
@ -234,8 +233,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
// create debug variable declarations for variables and allocate all local variables // create debug variable declarations for variables and allocate all local variables
for (var_list) |var_scope, i| { for (var_list) |var_scope, i| {
const var_type = switch (var_scope.data) { const var_type = switch (var_scope.data) {
Scope.Var.Data.Const => unreachable, .Const => unreachable,
Scope.Var.Data.Param => |param| param.typ, .Param => |param| param.typ,
}; };
// if (!type_has_bits(var->value->type)) { // if (!type_has_bits(var->value->type)) {
// continue; // continue;
@ -266,7 +265,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
var_scope.data.Param.llvm_value = llvm.GetParam(llvm_fn, @intCast(c_uint, i)); var_scope.data.Param.llvm_value = llvm.GetParam(llvm_fn, @intCast(c_uint, i));
} else { } else {
// gen_type = var->value->type; // gen_type = var->value->type;
var_scope.data.Param.llvm_value = try renderAlloca(ofile, var_type, var_scope.name, Type.Pointer.Align.Abi); var_scope.data.Param.llvm_value = try renderAlloca(ofile, var_type, var_scope.name, .Abi);
} }
// if (var->decl_node) { // if (var->decl_node) {
// var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), // var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
@ -300,8 +299,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
ofile, ofile,
llvm_param, llvm_param,
scope_var.data.Param.llvm_value, scope_var.data.Param.llvm_value,
Type.Pointer.Align.Abi, .Abi,
Type.Pointer.Vol.Non, .Non,
); );
} }
@ -383,8 +382,8 @@ fn renderLoadUntyped(
) !*llvm.Value { ) !*llvm.Value {
const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory; const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
switch (vol) { switch (vol) {
Type.Pointer.Vol.Non => {}, .Non => {},
Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1), .Volatile => llvm.SetVolatile(result, 1),
} }
llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.GetElementType(llvm.TypeOf(ptr)))); llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.GetElementType(llvm.TypeOf(ptr))));
return result; return result;
@ -414,8 +413,8 @@ pub fn renderStoreUntyped(
) !*llvm.Value { ) !*llvm.Value {
const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory; const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
switch (vol) { switch (vol) {
Type.Pointer.Vol.Non => {}, .Non => {},
Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1), .Volatile => llvm.SetVolatile(result, 1),
} }
llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.TypeOf(value))); llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.TypeOf(value)));
return result; return result;
@ -445,7 +444,7 @@ pub fn renderAlloca(
pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 { pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
return switch (alignment) { return switch (alignment) {
Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type), .Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
Type.Pointer.Align.Override => |a| a, .Override => |a| a,
}; };
} }

View File

@ -5,7 +5,7 @@ const Allocator = mem.Allocator;
const Buffer = std.Buffer; const Buffer = std.Buffer;
const llvm = @import("llvm.zig"); const llvm = @import("llvm.zig");
const c = @import("c.zig"); const c = @import("c.zig");
const builtin = @import("builtin"); const builtin = std.builtin;
const Target = std.Target; const Target = std.Target;
const warn = std.debug.warn; const warn = std.debug.warn;
const Token = std.zig.Token; const Token = std.zig.Token;
@ -481,7 +481,7 @@ pub const Compilation = struct {
comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" }); comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" });
const opt_level = switch (build_mode) { const opt_level = switch (build_mode) {
builtin.Mode.Debug => llvm.CodeGenLevelNone, .Debug => llvm.CodeGenLevelNone,
else => llvm.CodeGenLevelAggressive, else => llvm.CodeGenLevelAggressive,
}; };
@ -594,11 +594,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = "type", .name = "type",
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = undefined, .typ = undefined,
.ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
}, },
.id = builtin.TypeId.Type, .id = .Type,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
.value = undefined, .value = undefined,
@ -612,11 +612,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = "void", .name = "void",
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &Type.MetaType.get(comp).base, .typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
.id = builtin.TypeId.Void, .id = .Void,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
}; };
@ -627,11 +627,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = "noreturn", .name = "noreturn",
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &Type.MetaType.get(comp).base, .typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
.id = builtin.TypeId.NoReturn, .id = .NoReturn,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
}; };
@ -642,11 +642,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = "comptime_int", .name = "comptime_int",
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &Type.MetaType.get(comp).base, .typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
.id = builtin.TypeId.ComptimeInt, .id = .ComptimeInt,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
}; };
@ -657,11 +657,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = "bool", .name = "bool",
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &Type.MetaType.get(comp).base, .typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
.id = builtin.TypeId.Bool, .id = .Bool,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
}; };
@ -670,7 +670,7 @@ pub const Compilation = struct {
comp.void_value = try comp.arena().create(Value.Void); comp.void_value = try comp.arena().create(Value.Void);
comp.void_value.* = Value.Void{ comp.void_value.* = Value.Void{
.base = Value{ .base = Value{
.id = Value.Id.Void, .id = .Void,
.typ = &Type.Void.get(comp).base, .typ = &Type.Void.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -679,7 +679,7 @@ pub const Compilation = struct {
comp.true_value = try comp.arena().create(Value.Bool); comp.true_value = try comp.arena().create(Value.Bool);
comp.true_value.* = Value.Bool{ comp.true_value.* = Value.Bool{
.base = Value{ .base = Value{
.id = Value.Id.Bool, .id = .Bool,
.typ = &Type.Bool.get(comp).base, .typ = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -689,7 +689,7 @@ pub const Compilation = struct {
comp.false_value = try comp.arena().create(Value.Bool); comp.false_value = try comp.arena().create(Value.Bool);
comp.false_value.* = Value.Bool{ comp.false_value.* = Value.Bool{
.base = Value{ .base = Value{
.id = Value.Id.Bool, .id = .Bool,
.typ = &Type.Bool.get(comp).base, .typ = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -699,7 +699,7 @@ pub const Compilation = struct {
comp.noreturn_value = try comp.arena().create(Value.NoReturn); comp.noreturn_value = try comp.arena().create(Value.NoReturn);
comp.noreturn_value.* = Value.NoReturn{ comp.noreturn_value.* = Value.NoReturn{
.base = Value{ .base = Value{
.id = Value.Id.NoReturn, .id = .NoReturn,
.typ = &Type.NoReturn.get(comp).base, .typ = &Type.NoReturn.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -711,11 +711,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = cint.zig_name, .name = cint.zig_name,
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &Type.MetaType.get(comp).base, .typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
.id = builtin.TypeId.Int, .id = .Int,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
.key = Type.Int.Key{ .key = Type.Int.Key{
@ -732,11 +732,11 @@ pub const Compilation = struct {
.base = Type{ .base = Type{
.name = "u8", .name = "u8",
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &Type.MetaType.get(comp).base, .typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
.id = builtin.TypeId.Int, .id = .Int,
.abi_alignment = Type.AbiAlignment.init(), .abi_alignment = Type.AbiAlignment.init(),
}, },
.key = Type.Int.Key{ .key = Type.Int.Key{
@ -884,15 +884,15 @@ pub const Compilation = struct {
while (ast_it.next()) |decl_ptr| { while (ast_it.next()) |decl_ptr| {
const decl = decl_ptr.*; const decl = decl_ptr.*;
switch (decl.id) { switch (decl.id) {
ast.Node.Id.Comptime => { .Comptime => {
const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", decl); const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", decl);
// TODO connect existing comptime decls to updated source files // TODO connect existing comptime decls to updated source files
try self.prelink_group.call(addCompTimeBlock, self, tree_scope, &decl_scope.base, comptime_node); try self.prelink_group.call(addCompTimeBlock, self, tree_scope, &decl_scope.base, comptime_node);
}, },
ast.Node.Id.VarDecl => @panic("TODO"), .VarDecl => @panic("TODO"),
ast.Node.Id.FnProto => { .FnProto => {
const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else { const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else {
@ -945,7 +945,7 @@ pub const Compilation = struct {
try group.call(addTopLevelDecl, self, &fn_decl.base, locked_table); try group.call(addTopLevelDecl, self, &fn_decl.base, locked_table);
} }
}, },
ast.Node.Id.TestDecl => @panic("TODO"), .TestDecl => @panic("TODO"),
else => unreachable, else => unreachable,
} }
} }
@ -1285,12 +1285,12 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib
/// The function that actually does the generation. /// The function that actually does the generation.
async fn generateDecl(comp: *Compilation, decl: *Decl) !void { async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
switch (decl.id) { switch (decl.id) {
Decl.Id.Var => @panic("TODO"), .Var => @panic("TODO"),
Decl.Id.Fn => { .Fn => {
const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl); const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
return generateDeclFn(comp, fn_decl); return generateDeclFn(comp, fn_decl);
}, },
Decl.Id.CompTime => @panic("TODO"), .CompTime => @panic("TODO"),
} }
} }
@ -1385,8 +1385,8 @@ async fn analyzeFnType(
fn_proto: *ast.Node.FnProto, fn_proto: *ast.Node.FnProto,
) !*Type.Fn { ) !*Type.Fn {
const return_type_node = switch (fn_proto.return_type) { const return_type_node = switch (fn_proto.return_type) {
ast.Node.FnProto.ReturnType.Explicit => |n| n, .Explicit => |n| n,
ast.Node.FnProto.ReturnType.InferErrorSet => |n| n, .InferErrorSet => |n| n,
}; };
const return_type = try comp.analyzeTypeExpr(tree_scope, scope, return_type_node); const return_type = try comp.analyzeTypeExpr(tree_scope, scope, return_type_node);
return_type.base.deref(comp); return_type.base.deref(comp);

View File

@ -29,7 +29,7 @@ pub const Decl = struct {
pub fn isExported(base: *const Decl, tree: *ast.Tree) bool { pub fn isExported(base: *const Decl, tree: *ast.Tree) bool {
switch (base.id) { switch (base.id) {
Id.Fn => { .Fn => {
const fn_decl = @fieldParentPtr(Fn, "base", base); const fn_decl = @fieldParentPtr(Fn, "base", base);
return fn_decl.isExported(tree); return fn_decl.isExported(tree);
}, },
@ -39,7 +39,7 @@ pub const Decl = struct {
pub fn getSpan(base: *const Decl) errmsg.Span { pub fn getSpan(base: *const Decl) errmsg.Span {
switch (base.id) { switch (base.id) {
Id.Fn => { .Fn => {
const fn_decl = @fieldParentPtr(Fn, "base", base); const fn_decl = @fieldParentPtr(Fn, "base", base);
const fn_proto = fn_decl.fn_proto; const fn_proto = fn_decl.fn_proto;
const start = fn_proto.fn_token; const start = fn_proto.fn_token;
@ -69,21 +69,18 @@ pub const Decl = struct {
pub const Fn = struct { pub const Fn = struct {
base: Decl, base: Decl,
value: Val, value: union(enum) {
fn_proto: *ast.Node.FnProto, Unresolved,
// TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
pub const Val = union(enum) {
Unresolved: void,
Fn: *Value.Fn, Fn: *Value.Fn,
FnProto: *Value.FnProto, FnProto: *Value.FnProto,
}; },
fn_proto: *ast.Node.FnProto,
pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 { pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 {
return if (self.fn_proto.extern_export_inline_token) |tok_index| x: { return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {
const token = tree.tokens.at(tok_index); const token = tree.tokens.at(tok_index);
break :x switch (token.id) { break :x switch (token.id) {
Token.Id.Extern => tree.tokenSlicePtr(token), .Extern => tree.tokenSlicePtr(token),
else => null, else => null,
}; };
} else null; } else null;
@ -92,7 +89,7 @@ pub const Decl = struct {
pub fn isExported(self: Fn, tree: *ast.Tree) bool { pub fn isExported(self: Fn, tree: *ast.Tree) bool {
if (self.fn_proto.extern_export_inline_token) |tok_index| { if (self.fn_proto.extern_export_inline_token) |tok_index| {
const token = tree.tokens.at(tok_index); const token = tree.tokens.at(tok_index);
return token.id == Token.Id.Keyword_export; return token.id == .Keyword_export;
} else { } else {
return false; return false;
} }

View File

@ -62,17 +62,17 @@ pub const Msg = struct {
pub fn destroy(self: *Msg) void { pub fn destroy(self: *Msg) void {
switch (self.data) { switch (self.data) {
Data.Cli => |cli| { .Cli => |cli| {
cli.allocator.free(self.text); cli.allocator.free(self.text);
cli.allocator.free(self.realpath); cli.allocator.free(self.realpath);
cli.allocator.destroy(self); cli.allocator.destroy(self);
}, },
Data.PathAndTree => |path_and_tree| { .PathAndTree => |path_and_tree| {
path_and_tree.allocator.free(self.text); path_and_tree.allocator.free(self.text);
path_and_tree.allocator.free(self.realpath); path_and_tree.allocator.free(self.realpath);
path_and_tree.allocator.destroy(self); path_and_tree.allocator.destroy(self);
}, },
Data.ScopeAndComp => |scope_and_comp| { .ScopeAndComp => |scope_and_comp| {
scope_and_comp.tree_scope.base.deref(scope_and_comp.compilation); scope_and_comp.tree_scope.base.deref(scope_and_comp.compilation);
scope_and_comp.compilation.gpa().free(self.text); scope_and_comp.compilation.gpa().free(self.text);
scope_and_comp.compilation.gpa().free(self.realpath); scope_and_comp.compilation.gpa().free(self.realpath);
@ -83,11 +83,11 @@ pub const Msg = struct {
fn getAllocator(self: *const Msg) *mem.Allocator { fn getAllocator(self: *const Msg) *mem.Allocator {
switch (self.data) { switch (self.data) {
Data.Cli => |cli| return cli.allocator, .Cli => |cli| return cli.allocator,
Data.PathAndTree => |path_and_tree| { .PathAndTree => |path_and_tree| {
return path_and_tree.allocator; return path_and_tree.allocator;
}, },
Data.ScopeAndComp => |scope_and_comp| { .ScopeAndComp => |scope_and_comp| {
return scope_and_comp.compilation.gpa(); return scope_and_comp.compilation.gpa();
}, },
} }
@ -95,11 +95,11 @@ pub const Msg = struct {
pub fn getTree(self: *const Msg) *ast.Tree { pub fn getTree(self: *const Msg) *ast.Tree {
switch (self.data) { switch (self.data) {
Data.Cli => unreachable, .Cli => unreachable,
Data.PathAndTree => |path_and_tree| { .PathAndTree => |path_and_tree| {
return path_and_tree.tree; return path_and_tree.tree;
}, },
Data.ScopeAndComp => |scope_and_comp| { .ScopeAndComp => |scope_and_comp| {
return scope_and_comp.tree_scope.tree; return scope_and_comp.tree_scope.tree;
}, },
} }
@ -107,9 +107,9 @@ pub const Msg = struct {
pub fn getSpan(self: *const Msg) Span { pub fn getSpan(self: *const Msg) Span {
return switch (self.data) { return switch (self.data) {
Data.Cli => unreachable, .Cli => unreachable,
Data.PathAndTree => |path_and_tree| path_and_tree.span, .PathAndTree => |path_and_tree| path_and_tree.span,
Data.ScopeAndComp => |scope_and_comp| scope_and_comp.span, .ScopeAndComp => |scope_and_comp| scope_and_comp.span,
}; };
} }
@ -230,7 +230,7 @@ pub const Msg = struct {
pub fn printToStream(msg: *const Msg, stream: var, color_on: bool) !void { pub fn printToStream(msg: *const Msg, stream: var, color_on: bool) !void {
switch (msg.data) { switch (msg.data) {
Data.Cli => { .Cli => {
try stream.print("{}:-:-: error: {}\n", msg.realpath, msg.text); try stream.print("{}:-:-: error: {}\n", msg.realpath, msg.text);
return; return;
}, },
@ -279,9 +279,9 @@ pub const Msg = struct {
pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void { pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {
const color_on = switch (color) { const color_on = switch (color) {
Color.Auto => file.isTty(), .Auto => file.isTty(),
Color.On => true, .On => true,
Color.Off => false, .Off => false,
}; };
var stream = &file.outStream().stream; var stream = &file.outStream().stream;
return msg.printToStream(stream, color_on); return msg.printToStream(stream, color_on);

View File

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
const Scope = @import("scope.zig").Scope; const Scope = @import("scope.zig").Scope;
const ast = std.zig.ast; const ast = std.zig.ast;
@ -33,13 +32,13 @@ pub const IrVal = union(enum) {
pub fn dump(self: IrVal) void { pub fn dump(self: IrVal) void {
switch (self) { switch (self) {
IrVal.Unknown => std.debug.warn("Unknown"), .Unknown => std.debug.warn("Unknown"),
IrVal.KnownType => |typ| { .KnownType => |typ| {
std.debug.warn("KnownType("); std.debug.warn("KnownType(");
typ.dump(); typ.dump();
std.debug.warn(")"); std.debug.warn(")");
}, },
IrVal.KnownValue => |value| { .KnownValue => |value| {
std.debug.warn("KnownValue("); std.debug.warn("KnownValue(");
value.dump(); value.dump();
std.debug.warn(")"); std.debug.warn(")");
@ -113,37 +112,37 @@ pub const Inst = struct {
pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst { pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
switch (base.id) { switch (base.id) {
Id.Return => return @fieldParentPtr(Return, "base", base).analyze(ira), .Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
Id.Const => return @fieldParentPtr(Const, "base", base).analyze(ira), .Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
Id.Call => return @fieldParentPtr(Call, "base", base).analyze(ira), .Call => return @fieldParentPtr(Call, "base", base).analyze(ira),
Id.DeclRef => return @fieldParentPtr(DeclRef, "base", base).analyze(ira), .DeclRef => return @fieldParentPtr(DeclRef, "base", base).analyze(ira),
Id.Ref => return @fieldParentPtr(Ref, "base", base).analyze(ira), .Ref => return @fieldParentPtr(Ref, "base", base).analyze(ira),
Id.DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira), .DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira),
Id.CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira), .CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira),
Id.Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira), .Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira),
Id.Br => return @fieldParentPtr(Br, "base", base).analyze(ira), .Br => return @fieldParentPtr(Br, "base", base).analyze(ira),
Id.AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira), .AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira),
Id.PtrType => return @fieldParentPtr(PtrType, "base", base).analyze(ira), .PtrType => return @fieldParentPtr(PtrType, "base", base).analyze(ira),
Id.VarPtr => return @fieldParentPtr(VarPtr, "base", base).analyze(ira), .VarPtr => return @fieldParentPtr(VarPtr, "base", base).analyze(ira),
Id.LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).analyze(ira), .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).analyze(ira),
} }
} }
pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) { pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
switch (base.id) { switch (base.id) {
Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val), .Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val), .Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
Id.Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val), .Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val),
Id.VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val), .VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val),
Id.LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val), .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val),
Id.DeclRef => unreachable, .DeclRef => unreachable,
Id.PtrType => unreachable, .PtrType => unreachable,
Id.Ref => @panic("TODO"), .Ref => @panic("TODO"),
Id.DeclVar => @panic("TODO"), .DeclVar => @panic("TODO"),
Id.CheckVoidStmt => @panic("TODO"), .CheckVoidStmt => @panic("TODO"),
Id.Phi => @panic("TODO"), .Phi => @panic("TODO"),
Id.Br => @panic("TODO"), .Br => @panic("TODO"),
Id.AddImplicitReturnType => @panic("TODO"), .AddImplicitReturnType => @panic("TODO"),
} }
} }
@ -165,7 +164,7 @@ pub const Inst = struct {
param.ref_count -= 1; param.ref_count -= 1;
const child = param.child orelse return error.SemanticAnalysisFailed; const child = param.child orelse return error.SemanticAnalysisFailed;
switch (child.val) { switch (child.val) {
IrVal.Unknown => return error.SemanticAnalysisFailed, .Unknown => return error.SemanticAnalysisFailed,
else => return child, else => return child,
} }
} }
@ -213,9 +212,9 @@ pub const Inst = struct {
/// asserts that the type is known /// asserts that the type is known
fn getKnownType(self: *Inst) *Type { fn getKnownType(self: *Inst) *Type {
switch (self.val) { switch (self.val) {
IrVal.KnownType => |typ| return typ, .KnownType => |typ| return typ,
IrVal.KnownValue => |value| return value.typ, .KnownValue => |value| return value.typ,
IrVal.Unknown => unreachable, .Unknown => unreachable,
} }
} }
@ -225,14 +224,14 @@ pub const Inst = struct {
pub fn isNoReturn(base: *const Inst) bool { pub fn isNoReturn(base: *const Inst) bool {
switch (base.val) { switch (base.val) {
IrVal.Unknown => return false, .Unknown => return false,
IrVal.KnownValue => |x| return x.typ.id == Type.Id.NoReturn, .KnownValue => |x| return x.typ.id == .NoReturn,
IrVal.KnownType => |typ| return typ.id == Type.Id.NoReturn, .KnownType => |typ| return typ.id == .NoReturn,
} }
} }
pub fn isCompTime(base: *const Inst) bool { pub fn isCompTime(base: *const Inst) bool {
return base.val == IrVal.KnownValue; return base.val == .KnownValue;
} }
pub fn linkToParent(self: *Inst, parent: *Inst) void { pub fn linkToParent(self: *Inst, parent: *Inst) void {
@ -445,8 +444,8 @@ pub const Inst = struct {
.child_type = elem_type, .child_type = elem_type,
.mut = self.params.mut, .mut = self.params.mut,
.vol = self.params.volatility, .vol = self.params.volatility,
.size = Type.Pointer.Size.One, .size = .One,
.alignment = Type.Pointer.Align.Abi, .alignment = .Abi,
}); });
// TODO: potentially set the hint that this is a stack pointer. But it might not be - this // TODO: potentially set the hint that this is a stack pointer. But it might not be - this
// could be a ref of a global, for example // could be a ref of a global, for example
@ -479,20 +478,20 @@ pub const Inst = struct {
else => return error.SemanticAnalysisFailed, else => return error.SemanticAnalysisFailed,
}; };
switch (self.params.decl.id) { switch (self.params.decl.id) {
Decl.Id.CompTime => unreachable, .CompTime => unreachable,
Decl.Id.Var => return error.Unimplemented, .Var => return error.Unimplemented,
Decl.Id.Fn => { .Fn => {
const fn_decl = @fieldParentPtr(Decl.Fn, "base", self.params.decl); const fn_decl = @fieldParentPtr(Decl.Fn, "base", self.params.decl);
const decl_val = switch (fn_decl.value) { const decl_val = switch (fn_decl.value) {
Decl.Fn.Val.Unresolved => unreachable, .Unresolved => unreachable,
Decl.Fn.Val.Fn => |fn_val| &fn_val.base, .Fn => |fn_val| &fn_val.base,
Decl.Fn.Val.FnProto => |fn_proto| &fn_proto.base, .FnProto => |fn_proto| &fn_proto.base,
}; };
switch (self.params.lval) { switch (self.params.lval) {
LVal.None => { .None => {
return ira.irb.buildConstValue(self.base.scope, self.base.span, decl_val); return ira.irb.buildConstValue(self.base.scope, self.base.span, decl_val);
}, },
LVal.Ptr => return error.Unimplemented, .Ptr => return error.Unimplemented,
} }
}, },
} }
@ -519,20 +518,20 @@ pub const Inst = struct {
pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst { pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
switch (self.params.var_scope.data) { switch (self.params.var_scope.data) {
Scope.Var.Data.Const => @panic("TODO"), .Const => @panic("TODO"),
Scope.Var.Data.Param => |param| { .Param => |param| {
const new_inst = try ira.irb.build( const new_inst = try ira.irb.build(
Inst.VarPtr, .VarPtr,
self.base.scope, self.base.scope,
self.base.span, self.base.span,
Inst.VarPtr.Params{ .var_scope = self.params.var_scope }, Inst.VarPtr.Params{ .var_scope = self.params.var_scope },
); );
const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
.child_type = param.typ, .child_type = param.typ,
.mut = Type.Pointer.Mut.Const, .mut = .Const,
.vol = Type.Pointer.Vol.Non, .vol = .Non,
.size = Type.Pointer.Size.One, .size = .One,
.alignment = Type.Pointer.Align.Abi, .alignment = .Abi,
}); });
new_inst.val = IrVal{ .KnownType = &ptr_type.base }; new_inst.val = IrVal{ .KnownType = &ptr_type.base };
return new_inst; return new_inst;
@ -542,8 +541,8 @@ pub const Inst = struct {
pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value { pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
switch (self.params.var_scope.data) { switch (self.params.var_scope.data) {
Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass .Const => unreachable, // turned into Inst.Const in analyze pass
Scope.Var.Data.Param => |param| return param.llvm_value, .Param => |param| return param.llvm_value,
} }
} }
}; };
@ -567,7 +566,7 @@ pub const Inst = struct {
pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst { pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
const target = try self.params.target.getAsParam(); const target = try self.params.target.getAsParam();
const target_type = target.getKnownType(); const target_type = target.getKnownType();
if (target_type.id != Type.Id.Pointer) { if (target_type.id != .Pointer) {
try ira.addCompileError(self.base.span, "dereference of non pointer type '{}'", target_type.name); try ira.addCompileError(self.base.span, "dereference of non pointer type '{}'", target_type.name);
return error.SemanticAnalysisFailed; return error.SemanticAnalysisFailed;
} }
@ -715,7 +714,7 @@ pub const Inst = struct {
pub fn analyze(self: *const CheckVoidStmt, ira: *Analyze) !*Inst { pub fn analyze(self: *const CheckVoidStmt, ira: *Analyze) !*Inst {
const target = try self.params.target.getAsParam(); const target = try self.params.target.getAsParam();
if (target.getKnownType().id != Type.Id.Void) { if (target.getKnownType().id != .Void) {
try ira.addCompileError(self.base.span, "expression value is ignored"); try ira.addCompileError(self.base.span, "expression value is ignored");
return error.SemanticAnalysisFailed; return error.SemanticAnalysisFailed;
} }
@ -838,7 +837,7 @@ pub const Inst = struct {
const target = try self.params.target.getAsParam(); const target = try self.params.target.getAsParam();
const target_type = target.getKnownType(); const target_type = target.getKnownType();
switch (target_type.id) { switch (target_type.id) {
Type.Id.ErrorUnion => { .ErrorUnion => {
return error.Unimplemented; return error.Unimplemented;
// if (instr_is_comptime(value)) { // if (instr_is_comptime(value)) {
// ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad); // ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
@ -868,7 +867,7 @@ pub const Inst = struct {
// ir_build_test_err_from(&ira->new_irb, &instruction->base, value); // ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
// return ira->codegen->builtin_types.entry_bool; // return ira->codegen->builtin_types.entry_bool;
}, },
Type.Id.ErrorSet => { .ErrorSet => {
return ira.irb.buildConstBool(self.base.scope, self.base.span, true); return ira.irb.buildConstBool(self.base.scope, self.base.span, true);
}, },
else => { else => {
@ -1081,120 +1080,120 @@ pub const Builder = struct {
pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst { pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
switch (node.id) { switch (node.id) {
ast.Node.Id.Root => unreachable, .Root => unreachable,
ast.Node.Id.Use => unreachable, .Use => unreachable,
ast.Node.Id.TestDecl => unreachable, .TestDecl => unreachable,
ast.Node.Id.VarDecl => return error.Unimplemented, .VarDecl => return error.Unimplemented,
ast.Node.Id.Defer => return error.Unimplemented, .Defer => return error.Unimplemented,
ast.Node.Id.InfixOp => return error.Unimplemented, .InfixOp => return error.Unimplemented,
ast.Node.Id.PrefixOp => { .PrefixOp => {
const prefix_op = @fieldParentPtr(ast.Node.PrefixOp, "base", node); const prefix_op = @fieldParentPtr(ast.Node.PrefixOp, "base", node);
switch (prefix_op.op) { switch (prefix_op.op) {
ast.Node.PrefixOp.Op.AddressOf => return error.Unimplemented, .AddressOf => return error.Unimplemented,
ast.Node.PrefixOp.Op.ArrayType => |n| return error.Unimplemented, .ArrayType => |n| return error.Unimplemented,
ast.Node.PrefixOp.Op.Await => return error.Unimplemented, .Await => return error.Unimplemented,
ast.Node.PrefixOp.Op.BitNot => return error.Unimplemented, .BitNot => return error.Unimplemented,
ast.Node.PrefixOp.Op.BoolNot => return error.Unimplemented, .BoolNot => return error.Unimplemented,
ast.Node.PrefixOp.Op.Cancel => return error.Unimplemented, .Cancel => return error.Unimplemented,
ast.Node.PrefixOp.Op.OptionalType => return error.Unimplemented, .OptionalType => return error.Unimplemented,
ast.Node.PrefixOp.Op.Negation => return error.Unimplemented, .Negation => return error.Unimplemented,
ast.Node.PrefixOp.Op.NegationWrap => return error.Unimplemented, .NegationWrap => return error.Unimplemented,
ast.Node.PrefixOp.Op.Resume => return error.Unimplemented, .Resume => return error.Unimplemented,
ast.Node.PrefixOp.Op.PtrType => |ptr_info| { .PtrType => |ptr_info| {
const inst = try irb.genPtrType(prefix_op, ptr_info, scope); const inst = try irb.genPtrType(prefix_op, ptr_info, scope);
return irb.lvalWrap(scope, inst, lval); return irb.lvalWrap(scope, inst, lval);
}, },
ast.Node.PrefixOp.Op.SliceType => |ptr_info| return error.Unimplemented, .SliceType => |ptr_info| return error.Unimplemented,
ast.Node.PrefixOp.Op.Try => return error.Unimplemented, .Try => return error.Unimplemented,
} }
}, },
ast.Node.Id.SuffixOp => { .SuffixOp => {
const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node); const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node);
switch (suffix_op.op) { switch (suffix_op.op) {
@TagType(ast.Node.SuffixOp.Op).Call => |*call| { .Call => |*call| {
const inst = try irb.genCall(suffix_op, call, scope); const inst = try irb.genCall(suffix_op, call, scope);
return irb.lvalWrap(scope, inst, lval); return irb.lvalWrap(scope, inst, lval);
}, },
@TagType(ast.Node.SuffixOp.Op).ArrayAccess => |n| return error.Unimplemented, .ArrayAccess => |n| return error.Unimplemented,
@TagType(ast.Node.SuffixOp.Op).Slice => |slice| return error.Unimplemented, .Slice => |slice| return error.Unimplemented,
@TagType(ast.Node.SuffixOp.Op).ArrayInitializer => |init_list| return error.Unimplemented, .ArrayInitializer => |init_list| return error.Unimplemented,
@TagType(ast.Node.SuffixOp.Op).StructInitializer => |init_list| return error.Unimplemented, .StructInitializer => |init_list| return error.Unimplemented,
@TagType(ast.Node.SuffixOp.Op).Deref => return error.Unimplemented, .Deref => return error.Unimplemented,
@TagType(ast.Node.SuffixOp.Op).UnwrapOptional => return error.Unimplemented, .UnwrapOptional => return error.Unimplemented,
} }
}, },
ast.Node.Id.Switch => return error.Unimplemented, .Switch => return error.Unimplemented,
ast.Node.Id.While => return error.Unimplemented, .While => return error.Unimplemented,
ast.Node.Id.For => return error.Unimplemented, .For => return error.Unimplemented,
ast.Node.Id.If => return error.Unimplemented, .If => return error.Unimplemented,
ast.Node.Id.ControlFlowExpression => { .ControlFlowExpression => {
const control_flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", node); const control_flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", node);
return irb.genControlFlowExpr(control_flow_expr, scope, lval); return irb.genControlFlowExpr(control_flow_expr, scope, lval);
}, },
ast.Node.Id.Suspend => return error.Unimplemented, .Suspend => return error.Unimplemented,
ast.Node.Id.VarType => return error.Unimplemented, .VarType => return error.Unimplemented,
ast.Node.Id.ErrorType => return error.Unimplemented, .ErrorType => return error.Unimplemented,
ast.Node.Id.FnProto => return error.Unimplemented, .FnProto => return error.Unimplemented,
ast.Node.Id.PromiseType => return error.Unimplemented, .PromiseType => return error.Unimplemented,
ast.Node.Id.IntegerLiteral => { .IntegerLiteral => {
const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node); const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node);
return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval); return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval);
}, },
ast.Node.Id.FloatLiteral => return error.Unimplemented, .FloatLiteral => return error.Unimplemented,
ast.Node.Id.StringLiteral => { .StringLiteral => {
const str_lit = @fieldParentPtr(ast.Node.StringLiteral, "base", node); const str_lit = @fieldParentPtr(ast.Node.StringLiteral, "base", node);
const inst = try irb.genStrLit(str_lit, scope); const inst = try irb.genStrLit(str_lit, scope);
return irb.lvalWrap(scope, inst, lval); return irb.lvalWrap(scope, inst, lval);
}, },
ast.Node.Id.MultilineStringLiteral => return error.Unimplemented, .MultilineStringLiteral => return error.Unimplemented,
ast.Node.Id.CharLiteral => return error.Unimplemented, .CharLiteral => return error.Unimplemented,
ast.Node.Id.BoolLiteral => return error.Unimplemented, .BoolLiteral => return error.Unimplemented,
ast.Node.Id.NullLiteral => return error.Unimplemented, .NullLiteral => return error.Unimplemented,
ast.Node.Id.UndefinedLiteral => return error.Unimplemented, .UndefinedLiteral => return error.Unimplemented,
ast.Node.Id.Unreachable => return error.Unimplemented, .Unreachable => return error.Unimplemented,
ast.Node.Id.Identifier => { .Identifier => {
const identifier = @fieldParentPtr(ast.Node.Identifier, "base", node); const identifier = @fieldParentPtr(ast.Node.Identifier, "base", node);
return irb.genIdentifier(identifier, scope, lval); return irb.genIdentifier(identifier, scope, lval);
}, },
ast.Node.Id.GroupedExpression => { .GroupedExpression => {
const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node); const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node);
return irb.genNode(grouped_expr.expr, scope, lval); return irb.genNode(grouped_expr.expr, scope, lval);
}, },
ast.Node.Id.BuiltinCall => return error.Unimplemented, .BuiltinCall => return error.Unimplemented,
ast.Node.Id.ErrorSetDecl => return error.Unimplemented, .ErrorSetDecl => return error.Unimplemented,
ast.Node.Id.ContainerDecl => return error.Unimplemented, .ContainerDecl => return error.Unimplemented,
ast.Node.Id.Asm => return error.Unimplemented, .Asm => return error.Unimplemented,
ast.Node.Id.Comptime => return error.Unimplemented, .Comptime => return error.Unimplemented,
ast.Node.Id.Block => { .Block => {
const block = @fieldParentPtr(ast.Node.Block, "base", node); const block = @fieldParentPtr(ast.Node.Block, "base", node);
const inst = try irb.genBlock(block, scope); const inst = try irb.genBlock(block, scope);
return irb.lvalWrap(scope, inst, lval); return irb.lvalWrap(scope, inst, lval);
}, },
ast.Node.Id.DocComment => return error.Unimplemented, .DocComment => return error.Unimplemented,
ast.Node.Id.SwitchCase => return error.Unimplemented, .SwitchCase => return error.Unimplemented,
ast.Node.Id.SwitchElse => return error.Unimplemented, .SwitchElse => return error.Unimplemented,
ast.Node.Id.Else => return error.Unimplemented, .Else => return error.Unimplemented,
ast.Node.Id.Payload => return error.Unimplemented, .Payload => return error.Unimplemented,
ast.Node.Id.PointerPayload => return error.Unimplemented, .PointerPayload => return error.Unimplemented,
ast.Node.Id.PointerIndexPayload => return error.Unimplemented, .PointerIndexPayload => return error.Unimplemented,
ast.Node.Id.ContainerField => return error.Unimplemented, .ContainerField => return error.Unimplemented,
ast.Node.Id.ErrorTag => return error.Unimplemented, .ErrorTag => return error.Unimplemented,
ast.Node.Id.AsmInput => return error.Unimplemented, .AsmInput => return error.Unimplemented,
ast.Node.Id.AsmOutput => return error.Unimplemented, .AsmOutput => return error.Unimplemented,
ast.Node.Id.ParamDecl => return error.Unimplemented, .ParamDecl => return error.Unimplemented,
ast.Node.Id.FieldInitializer => return error.Unimplemented, .FieldInitializer => return error.Unimplemented,
ast.Node.Id.EnumLiteral => return error.Unimplemented, .EnumLiteral => return error.Unimplemented,
} }
} }
async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst { async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {
const fn_ref = try irb.genNode(suffix_op.lhs, scope, LVal.None); const fn_ref = try irb.genNode(suffix_op.lhs, scope, .None);
const args = try irb.arena().alloc(*Inst, call.params.len); const args = try irb.arena().alloc(*Inst, call.params.len);
var it = call.params.iterator(0); var it = call.params.iterator(0);
var i: usize = 0; var i: usize = 0;
while (it.next()) |arg_node_ptr| : (i += 1) { while (it.next()) |arg_node_ptr| : (i += 1) {
args[i] = try irb.genNode(arg_node_ptr.*, scope, LVal.None); args[i] = try irb.genNode(arg_node_ptr.*, scope, .None);
} }
//bool is_async = node->data.fn_call_expr.is_async; //bool is_async = node->data.fn_call_expr.is_async;
@ -1239,7 +1238,7 @@ pub const Builder = struct {
//} else { //} else {
// align_value = nullptr; // align_value = nullptr;
//} //}
const child_type = try irb.genNode(prefix_op.rhs, scope, LVal.None); const child_type = try irb.genNode(prefix_op.rhs, scope, .None);
//uint32_t bit_offset_start = 0; //uint32_t bit_offset_start = 0;
//if (node->data.pointer_type.bit_offset_start != nullptr) { //if (node->data.pointer_type.bit_offset_start != nullptr) {
@ -1273,9 +1272,9 @@ pub const Builder = struct {
return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{ return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{
.child_type = child_type, .child_type = child_type,
.mut = Type.Pointer.Mut.Mut, .mut = .Mut,
.vol = Type.Pointer.Vol.Non, .vol = .Non,
.size = Type.Pointer.Size.Many, .size = .Many,
.alignment = null, .alignment = null,
}); });
} }
@ -1287,15 +1286,15 @@ pub const Builder = struct {
var scope = target_scope; var scope = target_scope;
while (true) { while (true) {
switch (scope.id) { switch (scope.id) {
Scope.Id.CompTime => return true, .CompTime => return true,
Scope.Id.FnDef => return false, .FnDef => return false,
Scope.Id.Decls => unreachable, .Decls => unreachable,
Scope.Id.Root => unreachable, .Root => unreachable,
Scope.Id.AstTree => unreachable, .AstTree => unreachable,
Scope.Id.Block, .Block,
Scope.Id.Defer, .Defer,
Scope.Id.DeferExpr, .DeferExpr,
Scope.Id.Var, .Var,
=> scope = scope.parent.?, => scope = scope.parent.?,
} }
} }
@ -1374,8 +1373,8 @@ pub const Builder = struct {
const ptr_val = try Value.Ptr.createArrayElemPtr( const ptr_val = try Value.Ptr.createArrayElemPtr(
irb.comp, irb.comp,
array_val, array_val,
Type.Pointer.Mut.Const, .Const,
Type.Pointer.Size.Many, .Many,
0, 0,
); );
defer ptr_val.base.deref(irb.comp); defer ptr_val.base.deref(irb.comp);
@ -1438,7 +1437,7 @@ pub const Builder = struct {
child_scope = &defer_child_scope.base; child_scope = &defer_child_scope.base;
continue; continue;
} }
const statement_value = try irb.genNode(statement_node, child_scope, LVal.None); const statement_value = try irb.genNode(statement_node, child_scope, .None);
is_continuation_unreachable = statement_value.isNoReturn(); is_continuation_unreachable = statement_value.isNoReturn();
if (is_continuation_unreachable) { if (is_continuation_unreachable) {
@ -1481,7 +1480,7 @@ pub const Builder = struct {
try block_scope.incoming_values.append( try block_scope.incoming_values.append(
try irb.buildConstVoid(parent_scope, Span.token(block.rbrace), true), try irb.buildConstVoid(parent_scope, Span.token(block.rbrace), true),
); );
_ = try irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit); _ = try irb.genDefersForBlock(child_scope, outer_block_scope, .ScopeExit);
_ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{ _ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{
.dest_block = block_scope.end_block, .dest_block = block_scope.end_block,
@ -1496,7 +1495,7 @@ pub const Builder = struct {
}); });
} }
_ = try irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit); _ = try irb.genDefersForBlock(child_scope, outer_block_scope, .ScopeExit);
return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true); return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);
} }
@ -1507,9 +1506,9 @@ pub const Builder = struct {
lval: LVal, lval: LVal,
) !*Inst { ) !*Inst {
switch (control_flow_expr.kind) { switch (control_flow_expr.kind) {
ast.Node.ControlFlowExpression.Kind.Break => |arg| return error.Unimplemented, .Break => |arg| return error.Unimplemented,
ast.Node.ControlFlowExpression.Kind.Continue => |arg| return error.Unimplemented, .Continue => |arg| return error.Unimplemented,
ast.Node.ControlFlowExpression.Kind.Return => { .Return => {
const src_span = Span.token(control_flow_expr.ltoken); const src_span = Span.token(control_flow_expr.ltoken);
if (scope.findFnDef() == null) { if (scope.findFnDef() == null) {
try irb.comp.addCompileError( try irb.comp.addCompileError(
@ -1534,7 +1533,7 @@ pub const Builder = struct {
const outer_scope = irb.begin_scope.?; const outer_scope = irb.begin_scope.?;
const return_value = if (control_flow_expr.rhs) |rhs| blk: { const return_value = if (control_flow_expr.rhs) |rhs| blk: {
break :blk try irb.genNode(rhs, scope, LVal.None); break :blk try irb.genNode(rhs, scope, .None);
} else blk: { } else blk: {
break :blk try irb.buildConstVoid(scope, src_span, true); break :blk try irb.buildConstVoid(scope, src_span, true);
}; };
@ -1545,7 +1544,7 @@ pub const Builder = struct {
const err_block = try irb.createBasicBlock(scope, c"ErrRetErr"); const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");
const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk"); const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");
if (!have_err_defers) { if (!have_err_defers) {
_ = try irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit); _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
} }
const is_err = try irb.build( const is_err = try irb.build(
@ -1568,7 +1567,7 @@ pub const Builder = struct {
try irb.setCursorAtEndAndAppendBlock(err_block); try irb.setCursorAtEndAndAppendBlock(err_block);
if (have_err_defers) { if (have_err_defers) {
_ = try irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ErrorExit); _ = try irb.genDefersForBlock(scope, outer_scope, .ErrorExit);
} }
if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) { if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) {
_ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{}); _ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{});
@ -1580,7 +1579,7 @@ pub const Builder = struct {
try irb.setCursorAtEndAndAppendBlock(ok_block); try irb.setCursorAtEndAndAppendBlock(ok_block);
if (have_err_defers) { if (have_err_defers) {
_ = try irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit); _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
} }
_ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{ _ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{
.dest_block = ret_stmt_block, .dest_block = ret_stmt_block,
@ -1590,7 +1589,7 @@ pub const Builder = struct {
try irb.setCursorAtEndAndAppendBlock(ret_stmt_block); try irb.setCursorAtEndAndAppendBlock(ret_stmt_block);
return irb.genAsyncReturn(scope, src_span, return_value, false); return irb.genAsyncReturn(scope, src_span, return_value, false);
} else { } else {
_ = try irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit); _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
return irb.genAsyncReturn(scope, src_span, return_value, false); return irb.genAsyncReturn(scope, src_span, return_value, false);
} }
}, },
@ -1616,8 +1615,8 @@ pub const Builder = struct {
switch (lval) { switch (lval) {
// if (lval == LValPtr) { // if (lval == LValPtr) {
// return ir_build_ref(irb, scope, node, value, false, false); // return ir_build_ref(irb, scope, node, value, false, false);
LVal.Ptr => return error.Unimplemented, .Ptr => return error.Unimplemented,
LVal.None => return irb.buildConstValue(scope, src_span, &primitive_type.base), .None => return irb.buildConstValue(scope, src_span, &primitive_type.base),
} }
} }
} else |err| switch (err) { } else |err| switch (err) {
@ -1629,22 +1628,22 @@ pub const Builder = struct {
} }
switch (irb.findIdent(scope, name)) { switch (irb.findIdent(scope, name)) {
Ident.Decl => |decl| { .Decl => |decl| {
return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{ return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{
.decl = decl, .decl = decl,
.lval = lval, .lval = lval,
}); });
}, },
Ident.VarScope => |var_scope| { .VarScope => |var_scope| {
const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope }); const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope });
switch (lval) { switch (lval) {
LVal.Ptr => return var_ptr, .Ptr => return var_ptr,
LVal.None => { .None => {
return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr }); return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr });
}, },
} }
}, },
Ident.NotFound => {}, .NotFound => {},
} }
//if (node->owner->any_imports_failed) { //if (node->owner->any_imports_failed) {
@ -1671,25 +1670,25 @@ pub const Builder = struct {
var scope = inner_scope; var scope = inner_scope;
while (scope != outer_scope) { while (scope != outer_scope) {
switch (scope.id) { switch (scope.id) {
Scope.Id.Defer => { .Defer => {
const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope); const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);
switch (defer_scope.kind) { switch (defer_scope.kind) {
Scope.Defer.Kind.ScopeExit => result.scope_exit += 1, .ScopeExit => result.scope_exit += 1,
Scope.Defer.Kind.ErrorExit => result.error_exit += 1, .ErrorExit => result.error_exit += 1,
} }
scope = scope.parent orelse break; scope = scope.parent orelse break;
}, },
Scope.Id.FnDef => break, .FnDef => break,
Scope.Id.CompTime, .CompTime,
Scope.Id.Block, .Block,
Scope.Id.Decls, .Decls,
Scope.Id.Root, .Root,
Scope.Id.Var, .Var,
=> scope = scope.parent orelse break, => scope = scope.parent orelse break,
Scope.Id.DeferExpr => unreachable, .DeferExpr => unreachable,
Scope.Id.AstTree => unreachable, .AstTree => unreachable,
} }
} }
return result; return result;
@ -1705,18 +1704,18 @@ pub const Builder = struct {
var is_noreturn = false; var is_noreturn = false;
while (true) { while (true) {
switch (scope.id) { switch (scope.id) {
Scope.Id.Defer => { .Defer => {
const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope); const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);
const generate = switch (defer_scope.kind) { const generate = switch (defer_scope.kind) {
Scope.Defer.Kind.ScopeExit => true, .ScopeExit => true,
Scope.Defer.Kind.ErrorExit => gen_kind == Scope.Defer.Kind.ErrorExit, .ErrorExit => gen_kind == .ErrorExit,
}; };
if (generate) { if (generate) {
const defer_expr_scope = defer_scope.defer_expr_scope; const defer_expr_scope = defer_scope.defer_expr_scope;
const instruction = try irb.genNode( const instruction = try irb.genNode(
defer_expr_scope.expr_node, defer_expr_scope.expr_node,
&defer_expr_scope.base, &defer_expr_scope.base,
LVal.None, .None,
); );
if (instruction.isNoReturn()) { if (instruction.isNoReturn()) {
is_noreturn = true; is_noreturn = true;
@ -1730,32 +1729,32 @@ pub const Builder = struct {
} }
} }
}, },
Scope.Id.FnDef, .FnDef,
Scope.Id.Decls, .Decls,
Scope.Id.Root, .Root,
=> return is_noreturn, => return is_noreturn,
Scope.Id.CompTime, .CompTime,
Scope.Id.Block, .Block,
Scope.Id.Var, .Var,
=> scope = scope.parent orelse return is_noreturn, => scope = scope.parent orelse return is_noreturn,
Scope.Id.DeferExpr => unreachable, .DeferExpr => unreachable,
Scope.Id.AstTree => unreachable, .AstTree => unreachable,
} }
} }
} }
pub fn lvalWrap(irb: *Builder, scope: *Scope, instruction: *Inst, lval: LVal) !*Inst { pub fn lvalWrap(irb: *Builder, scope: *Scope, instruction: *Inst, lval: LVal) !*Inst {
switch (lval) { switch (lval) {
LVal.None => return instruction, .None => return instruction,
LVal.Ptr => { .Ptr => {
// We needed a pointer to a value, but we got a value. So we create // We needed a pointer to a value, but we got a value. So we create
// an instruction which just makes a const pointer of it. // an instruction which just makes a const pointer of it.
return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{ return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{
.target = instruction, .target = instruction,
.mut = Type.Pointer.Mut.Const, .mut = .Const,
.volatility = Type.Pointer.Vol.Non, .volatility = .Non,
}); });
}, },
} }
@ -1781,9 +1780,9 @@ pub const Builder = struct {
.scope = scope, .scope = scope,
.debug_id = self.next_debug_id, .debug_id = self.next_debug_id,
.val = switch (I.ir_val_init) { .val = switch (I.ir_val_init) {
IrVal.Init.Unknown => IrVal.Unknown, .Unknown => IrVal.Unknown,
IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base }, .NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base }, .Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
}, },
.ref_count = 0, .ref_count = 0,
.span = span, .span = span,
@ -1813,9 +1812,9 @@ pub const Builder = struct {
for (@field(inst.params, @memberName(I.Params, i))) |other| for (@field(inst.params, @memberName(I.Params, i))) |other|
other.ref(self); other.ref(self);
}, },
Type.Pointer.Mut, .Mut,
Type.Pointer.Vol, .Vol,
Type.Pointer.Size, .Size,
LVal, LVal,
*Decl, *Decl,
*Scope.Var, *Scope.Var,
@ -1915,8 +1914,8 @@ pub const Builder = struct {
var s = scope; var s = scope;
while (true) { while (true) {
switch (s.id) { switch (s.id) {
Scope.Id.Root => return Ident.NotFound, .Root => return .NotFound,
Scope.Id.Decls => { .Decls => {
const decls = @fieldParentPtr(Scope.Decls, "base", s); const decls = @fieldParentPtr(Scope.Decls, "base", s);
const locked_table = decls.table.acquireRead(); const locked_table = decls.table.acquireRead();
defer locked_table.release(); defer locked_table.release();
@ -1924,7 +1923,7 @@ pub const Builder = struct {
return Ident{ .Decl = entry.value }; return Ident{ .Decl = entry.value };
} }
}, },
Scope.Id.Var => { .Var => {
const var_scope = @fieldParentPtr(Scope.Var, "base", s); const var_scope = @fieldParentPtr(Scope.Var, "base", s);
if (mem.eql(u8, var_scope.name, name)) { if (mem.eql(u8, var_scope.name, name)) {
return Ident{ .VarScope = var_scope }; return Ident{ .VarScope = var_scope };
@ -2047,7 +2046,7 @@ const Analyze = struct {
fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst { fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst {
const dest_type = optional_dest_type orelse return target; const dest_type = optional_dest_type orelse return target;
const from_type = target.getKnownType(); const from_type = target.getKnownType();
if (from_type == dest_type or from_type.id == Type.Id.NoReturn) return target; if (from_type == dest_type or from_type.id == .NoReturn) return target;
return self.analyzeCast(target, target, dest_type); return self.analyzeCast(target, target, dest_type);
} }
@ -2311,7 +2310,7 @@ const Analyze = struct {
//} //}
// cast from comptime-known integer to another integer where the value fits // cast from comptime-known integer to another integer where the value fits
if (target.isCompTime() and (from_type.id == Type.Id.Int or from_type.id == Type.Id.ComptimeInt)) cast: { if (target.isCompTime() and (from_type.id == .Int or from_type.id == .ComptimeInt)) cast: {
const target_val = target.val.KnownValue; const target_val = target.val.KnownValue;
const from_int = &target_val.cast(Value.Int).?.big_int; const from_int = &target_val.cast(Value.Int).?.big_int;
const fits = fits: { const fits = fits: {
@ -2534,7 +2533,7 @@ pub async fn gen(
entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin. entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
try irb.setCursorAtEndAndAppendBlock(entry_block); try irb.setCursorAtEndAndAppendBlock(entry_block);
const result = try irb.genNode(body_node, scope, LVal.None); const result = try irb.genNode(body_node, scope, .None);
if (!result.isNoReturn()) { if (!result.isNoReturn()) {
// no need for save_err_ret_addr because this cannot return error // no need for save_err_ret_addr because this cannot return error
_ = try irb.genAsyncReturn(scope, Span.token(body_node.lastToken()), result, true); _ = try irb.genAsyncReturn(scope, Span.token(body_node.lastToken()), result, true);

View File

@ -73,7 +73,7 @@ pub const LibCInstallation = struct {
if (std.mem.eql(u8, name, key)) { if (std.mem.eql(u8, name, key)) {
found_keys[i].found = true; found_keys[i].found = true;
switch (@typeInfo(@typeOf(@field(self, key)))) { switch (@typeInfo(@typeOf(@field(self, key)))) {
builtin.TypeId.Optional => { .Optional => {
if (value.len == 0) { if (value.len == 0) {
@field(self, key) = null; @field(self, key) = null;
} else { } else {
@ -208,7 +208,7 @@ pub const LibCInstallation = struct {
} }
switch (exec_result.term) { switch (exec_result.term) {
std.ChildProcess.Term.Exited => |code| { .Exited => |code| {
if (code != 0) return error.CCompilerExitCode; if (code != 0) return error.CCompilerExitCode;
}, },
else => { else => {
@ -284,9 +284,9 @@ pub const LibCInstallation = struct {
const stream = &std.io.BufferOutStream.init(&result_buf).stream; const stream = &std.io.BufferOutStream.init(&result_buf).stream;
try stream.print("{}\\Lib\\{}\\ucrt\\", search.path, search.version); try stream.print("{}\\Lib\\{}\\ucrt\\", search.path, search.version);
switch (builtin.arch) { switch (builtin.arch) {
builtin.Arch.i386 => try stream.write("x86"), .i386 => try stream.write("x86"),
builtin.Arch.x86_64 => try stream.write("x64"), .x86_64 => try stream.write("x64"),
builtin.Arch.aarch64 => try stream.write("arm"), .aarch64 => try stream.write("arm"),
else => return error.UnsupportedArchitecture, else => return error.UnsupportedArchitecture,
} }
const ucrt_lib_path = try fs.path.join( const ucrt_lib_path = try fs.path.join(
@ -362,9 +362,9 @@ pub const LibCInstallation = struct {
const stream = &std.io.BufferOutStream.init(&result_buf).stream; const stream = &std.io.BufferOutStream.init(&result_buf).stream;
try stream.print("{}\\Lib\\{}\\um\\", search.path, search.version); try stream.print("{}\\Lib\\{}\\um\\", search.path, search.version);
switch (builtin.arch) { switch (builtin.arch) {
builtin.Arch.i386 => try stream.write("x86\\"), .i386 => try stream.write("x86\\"),
builtin.Arch.x86_64 => try stream.write("x64\\"), .x86_64 => try stream.write("x64\\"),
builtin.Arch.aarch64 => try stream.write("arm\\"), .aarch64 => try stream.write("arm\\"),
else => return error.UnsupportedArchitecture, else => return error.UnsupportedArchitecture,
} }
const kernel32_path = try fs.path.join( const kernel32_path = try fs.path.join(

View File

@ -1,10 +1,9 @@
const std = @import("std"); const std = @import("std");
const mem = std.mem; const mem = std.mem;
const c = @import("c.zig"); const c = @import("c.zig");
const builtin = @import("builtin");
const ObjectFormat = builtin.ObjectFormat;
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
const Target = std.Target; const Target = std.Target;
const ObjectFormat = Target.ObjectFormat;
const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const assert = std.debug.assert; const assert = std.debug.assert;
@ -26,7 +25,7 @@ pub async fn link(comp: *Compilation) !void {
.comp = comp, .comp = comp,
.arena = std.heap.ArenaAllocator.init(comp.gpa()), .arena = std.heap.ArenaAllocator.init(comp.gpa()),
.args = undefined, .args = undefined,
.link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe, .link_in_crt = comp.haveLibC() and comp.kind == .Exe,
.link_err = {}, .link_err = {},
.link_msg = undefined, .link_msg = undefined,
.libc = undefined, .libc = undefined,
@ -41,13 +40,13 @@ pub async fn link(comp: *Compilation) !void {
} else { } else {
ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst()); ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
switch (comp.kind) { switch (comp.kind) {
Compilation.Kind.Exe => { .Exe => {
try ctx.out_file_path.append(comp.target.exeFileExt()); try ctx.out_file_path.append(comp.target.exeFileExt());
}, },
Compilation.Kind.Lib => { .Lib => {
try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static)); try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static));
}, },
Compilation.Kind.Obj => { .Obj => {
try ctx.out_file_path.append(comp.target.objFileExt()); try ctx.out_file_path.append(comp.target.objFileExt());
}, },
} }
@ -121,21 +120,21 @@ fn linkDiagCallbackErrorable(ctx: *Context, msg: []const u8) !void {
fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType { fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType {
return switch (ofmt) { return switch (ofmt) {
ObjectFormat.unknown => c.ZigLLVM_UnknownObjectFormat, .unknown => c.ZigLLVM_UnknownObjectFormat,
ObjectFormat.coff => c.ZigLLVM_COFF, .coff => c.ZigLLVM_COFF,
ObjectFormat.elf => c.ZigLLVM_ELF, .elf => c.ZigLLVM_ELF,
ObjectFormat.macho => c.ZigLLVM_MachO, .macho => c.ZigLLVM_MachO,
ObjectFormat.wasm => c.ZigLLVM_Wasm, .wasm => c.ZigLLVM_Wasm,
}; };
} }
fn constructLinkerArgs(ctx: *Context) !void { fn constructLinkerArgs(ctx: *Context) !void {
switch (ctx.comp.target.getObjectFormat()) { switch (ctx.comp.target.getObjectFormat()) {
ObjectFormat.unknown => unreachable, .unknown => unreachable,
ObjectFormat.coff => return constructLinkerArgsCoff(ctx), .coff => return constructLinkerArgsCoff(ctx),
ObjectFormat.elf => return constructLinkerArgsElf(ctx), .elf => return constructLinkerArgsElf(ctx),
ObjectFormat.macho => return constructLinkerArgsMachO(ctx), .macho => return constructLinkerArgsMachO(ctx),
ObjectFormat.wasm => return constructLinkerArgsWasm(ctx), .wasm => return constructLinkerArgsWasm(ctx),
} }
} }
@ -324,9 +323,9 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
} }
switch (ctx.comp.target.getArch()) { switch (ctx.comp.target.getArch()) {
builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"), .i386 => try ctx.args.append(c"-MACHINE:X86"),
builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"), .x86_64 => try ctx.args.append(c"-MACHINE:X64"),
builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"), .aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
else => return error.UnsupportedLinkArchitecture, else => return error.UnsupportedLinkArchitecture,
} }
@ -336,7 +335,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
try ctx.args.append(c"/SUBSYSTEM:console"); try ctx.args.append(c"/SUBSYSTEM:console");
} }
const is_library = ctx.comp.kind == Compilation.Kind.Lib; const is_library = ctx.comp.kind == .Lib;
const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst()); const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());
try ctx.args.append(out_arg.ptr); try ctx.args.append(out_arg.ptr);
@ -349,7 +348,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
if (ctx.link_in_crt) { if (ctx.link_in_crt) {
const lib_str = if (ctx.comp.is_static) "lib" else ""; const lib_str = if (ctx.comp.is_static) "lib" else "";
const d_str = if (ctx.comp.build_mode == builtin.Mode.Debug) "d" else ""; const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str); const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);
@ -400,7 +399,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
try addFnObjects(ctx); try addFnObjects(ctx);
switch (ctx.comp.kind) { switch (ctx.comp.kind) {
Compilation.Kind.Exe, Compilation.Kind.Lib => { .Exe, .Lib => {
if (!ctx.comp.haveLibC()) { if (!ctx.comp.haveLibC()) {
@panic("TODO"); @panic("TODO");
//Buf *builtin_o_path = build_o(g, "builtin"); //Buf *builtin_o_path = build_o(g, "builtin");
@ -412,7 +411,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
//Buf *compiler_rt_o_path = build_compiler_rt(g); //Buf *compiler_rt_o_path = build_compiler_rt(g);
//lj->args.append(buf_ptr(compiler_rt_o_path)); //lj->args.append(buf_ptr(compiler_rt_o_path));
}, },
Compilation.Kind.Obj => {}, .Obj => {},
} }
//Buf *def_contents = buf_alloc(); //Buf *def_contents = buf_alloc();
@ -469,7 +468,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"-export_dynamic"); try ctx.args.append(c"-export_dynamic");
} }
const is_lib = ctx.comp.kind == Compilation.Kind.Lib; const is_lib = ctx.comp.kind == .Lib;
const shared = !ctx.comp.is_static and is_lib; const shared = !ctx.comp.is_static and is_lib;
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
try ctx.args.append(c"-static"); try ctx.args.append(c"-static");
@ -512,14 +511,14 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
const platform = try DarwinPlatform.get(ctx.comp); const platform = try DarwinPlatform.get(ctx.comp);
switch (platform.kind) { switch (platform.kind) {
DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"), .MacOS => try ctx.args.append(c"-macosx_version_min"),
DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"), .IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),
DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"), .IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),
} }
const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro); const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
try ctx.args.append(ver_str.ptr); try ctx.args.append(ver_str.ptr);
if (ctx.comp.kind == Compilation.Kind.Exe) { if (ctx.comp.kind == .Exe) {
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
try ctx.args.append(c"-no_pie"); try ctx.args.append(c"-no_pie");
} else { } else {
@ -542,7 +541,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"-lcrt0.o"); try ctx.args.append(c"-lcrt0.o");
} else { } else {
switch (platform.kind) { switch (platform.kind) {
DarwinPlatform.Kind.MacOS => { .MacOS => {
if (platform.versionLessThan(10, 5)) { if (platform.versionLessThan(10, 5)) {
try ctx.args.append(c"-lcrt1.o"); try ctx.args.append(c"-lcrt1.o");
} else if (platform.versionLessThan(10, 6)) { } else if (platform.versionLessThan(10, 6)) {
@ -551,8 +550,8 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"-lcrt1.10.6.o"); try ctx.args.append(c"-lcrt1.10.6.o");
} }
}, },
DarwinPlatform.Kind.IPhoneOS => { .IPhoneOS => {
if (ctx.comp.target.getArch() == builtin.Arch.aarch64) { if (ctx.comp.target.getArch() == .aarch64) {
// iOS does not need any crt1 files for arm64 // iOS does not need any crt1 files for arm64
} else if (platform.versionLessThan(3, 1)) { } else if (platform.versionLessThan(3, 1)) {
try ctx.args.append(c"-lcrt1.o"); try ctx.args.append(c"-lcrt1.o");
@ -560,7 +559,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"-lcrt1.3.1.o"); try ctx.args.append(c"-lcrt1.3.1.o");
} }
}, },
DarwinPlatform.Kind.IPhoneOSSimulator => {}, // no crt1.o needed .IPhoneOSSimulator => {}, // no crt1.o needed
} }
} }
@ -605,7 +604,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"dynamic_lookup"); try ctx.args.append(c"dynamic_lookup");
} }
if (platform.kind == DarwinPlatform.Kind.MacOS) { if (platform.kind == .MacOS) {
if (platform.versionLessThan(10, 5)) { if (platform.versionLessThan(10, 5)) {
try ctx.args.append(c"-lgcc_s.10.4"); try ctx.args.append(c"-lgcc_s.10.4");
} else if (platform.versionLessThan(10, 6)) { } else if (platform.versionLessThan(10, 6)) {
@ -659,17 +658,17 @@ const DarwinPlatform = struct {
fn get(comp: *Compilation) !DarwinPlatform { fn get(comp: *Compilation) !DarwinPlatform {
var result: DarwinPlatform = undefined; var result: DarwinPlatform = undefined;
const ver_str = switch (comp.darwin_version_min) { const ver_str = switch (comp.darwin_version_min) {
Compilation.DarwinVersionMin.MacOS => |ver| blk: { .MacOS => |ver| blk: {
result.kind = Kind.MacOS; result.kind = .MacOS;
break :blk ver; break :blk ver;
}, },
Compilation.DarwinVersionMin.Ios => |ver| blk: { .Ios => |ver| blk: {
result.kind = Kind.IPhoneOS; result.kind = .IPhoneOS;
break :blk ver; break :blk ver;
}, },
Compilation.DarwinVersionMin.None => blk: { .None => blk: {
assert(comp.target.getOs() == .macosx); assert(comp.target.getOs() == .macosx);
result.kind = Kind.MacOS; result.kind = .MacOS;
break :blk "10.14"; break :blk "10.14";
}, },
}; };
@ -686,11 +685,11 @@ const DarwinPlatform = struct {
return error.InvalidDarwinVersionString; return error.InvalidDarwinVersionString;
} }
if (result.kind == Kind.IPhoneOS) { if (result.kind == .IPhoneOS) {
switch (comp.target.getArch()) { switch (comp.target.getArch()) {
builtin.Arch.i386, .i386,
builtin.Arch.x86_64, .x86_64,
=> result.kind = Kind.IPhoneOSSimulator, => result.kind = .IPhoneOSSimulator,
else => {}, else => {},
} }
} }

View File

@ -1,4 +1,3 @@
const builtin = @import("builtin");
const c = @import("c.zig"); const c = @import("c.zig");
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
@ -269,7 +268,7 @@ pub const FnInline = extern enum {
}; };
fn removeNullability(comptime T: type) type { fn removeNullability(comptime T: type) type {
comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C); comptime assert(@typeInfo(T).Pointer.size == .C);
return *T.Child; return *T.Child;
} }

View File

@ -266,16 +266,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
const build_mode = blk: { const build_mode = blk: {
if (flags.single("mode")) |mode_flag| { if (flags.single("mode")) |mode_flag| {
if (mem.eql(u8, mode_flag, "debug")) { if (mem.eql(u8, mode_flag, "debug")) {
break :blk builtin.Mode.Debug; break :blk std.builtin.Mode.Debug;
} else if (mem.eql(u8, mode_flag, "release-fast")) { } else if (mem.eql(u8, mode_flag, "release-fast")) {
break :blk builtin.Mode.ReleaseFast; break :blk std.builtin.Mode.ReleaseFast;
} else if (mem.eql(u8, mode_flag, "release-safe")) { } else if (mem.eql(u8, mode_flag, "release-safe")) {
break :blk builtin.Mode.ReleaseSafe; break :blk std.builtin.Mode.ReleaseSafe;
} else if (mem.eql(u8, mode_flag, "release-small")) { } else if (mem.eql(u8, mode_flag, "release-small")) {
break :blk builtin.Mode.ReleaseSmall; break :blk std.builtin.Mode.ReleaseSmall;
} else unreachable; } else unreachable;
} else { } else {
break :blk builtin.Mode.Debug; break :blk std.builtin.Mode.Debug;
} }
}; };
@ -475,13 +475,13 @@ async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
count += 1; count += 1;
switch (build_event) { switch (build_event) {
Compilation.Event.Ok => { .Ok => {
stderr.print("Build {} succeeded\n", count) catch process.exit(1); stderr.print("Build {} succeeded\n", count) catch process.exit(1);
}, },
Compilation.Event.Error => |err| { .Error => |err| {
stderr.print("Build {} failed: {}\n", count, @errorName(err)) catch process.exit(1); stderr.print("Build {} failed: {}\n", count, @errorName(err)) catch process.exit(1);
}, },
Compilation.Event.Fail => |msgs| { .Fail => |msgs| {
stderr.print("Build {} compile errors:\n", count) catch process.exit(1); stderr.print("Build {} compile errors:\n", count) catch process.exit(1);
for (msgs) |msg| { for (msgs) |msg| {
defer msg.destroy(); defer msg.destroy();
@ -795,8 +795,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write("Operating Systems:\n"); try stdout.write("Operating Systems:\n");
{ {
comptime var i: usize = 0; comptime var i: usize = 0;
inline while (i < @memberCount(builtin.Os)) : (i += 1) { inline while (i < @memberCount(Target.Os)) : (i += 1) {
comptime const os_tag = @memberName(builtin.Os, i); comptime const os_tag = @memberName(Target.Os, i);
// NOTE: Cannot use empty string, see #918. // NOTE: Cannot use empty string, see #918.
comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n"; comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
@ -808,8 +808,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write("C ABIs:\n"); try stdout.write("C ABIs:\n");
{ {
comptime var i: usize = 0; comptime var i: usize = 0;
inline while (i < @memberCount(builtin.Abi)) : (i += 1) { inline while (i < @memberCount(Target.Abi)) : (i += 1) {
comptime const abi_tag = @memberName(builtin.Abi, i); comptime const abi_tag = @memberName(Target.Abi, i);
// NOTE: Cannot use empty string, see #918. // NOTE: Cannot use empty string, see #918.
comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n"; comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n";

View File

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
const Allocator = mem.Allocator; const Allocator = mem.Allocator;
const Decl = @import("decl.zig").Decl; const Decl = @import("decl.zig").Decl;
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
@ -28,15 +27,15 @@ pub const Scope = struct {
if (base.ref_count.decr() == 1) { if (base.ref_count.decr() == 1) {
if (base.parent) |parent| parent.deref(comp); if (base.parent) |parent| parent.deref(comp);
switch (base.id) { switch (base.id) {
Id.Root => @fieldParentPtr(Root, "base", base).destroy(comp), .Root => @fieldParentPtr(Root, "base", base).destroy(comp),
Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(comp), .Decls => @fieldParentPtr(Decls, "base", base).destroy(comp),
Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp), .Block => @fieldParentPtr(Block, "base", base).destroy(comp),
Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp), .FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp), .CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp), .Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp), .DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
Id.Var => @fieldParentPtr(Var, "base", base).destroy(comp), .Var => @fieldParentPtr(Var, "base", base).destroy(comp),
Id.AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp), .AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp),
} }
} }
} }
@ -46,7 +45,7 @@ pub const Scope = struct {
while (scope.parent) |parent| { while (scope.parent) |parent| {
scope = parent; scope = parent;
} }
assert(scope.id == Id.Root); assert(scope.id == .Root);
return @fieldParentPtr(Root, "base", scope); return @fieldParentPtr(Root, "base", scope);
} }
@ -54,17 +53,17 @@ pub const Scope = struct {
var scope = base; var scope = base;
while (true) { while (true) {
switch (scope.id) { switch (scope.id) {
Id.FnDef => return @fieldParentPtr(FnDef, "base", scope), .FnDef => return @fieldParentPtr(FnDef, "base", scope),
Id.Root, Id.Decls => return null, .Root, .Decls => return null,
Id.Block, .Block,
Id.Defer, .Defer,
Id.DeferExpr, .DeferExpr,
Id.CompTime, .CompTime,
Id.Var, .Var,
=> scope = scope.parent.?, => scope = scope.parent.?,
Id.AstTree => unreachable, .AstTree => unreachable,
} }
} }
} }
@ -73,20 +72,20 @@ pub const Scope = struct {
var scope = base; var scope = base;
while (true) { while (true) {
switch (scope.id) { switch (scope.id) {
Id.DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope), .DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope),
Id.FnDef, .FnDef,
Id.Decls, .Decls,
=> return null, => return null,
Id.Block, .Block,
Id.Defer, .Defer,
Id.CompTime, .CompTime,
Id.Root, .Root,
Id.Var, .Var,
=> scope = scope.parent orelse return null, => scope = scope.parent orelse return null,
Id.AstTree => unreachable, .AstTree => unreachable,
} }
} }
} }
@ -123,7 +122,7 @@ pub const Scope = struct {
const self = try comp.gpa().create(Root); const self = try comp.gpa().create(Root);
self.* = Root{ self.* = Root{
.base = Scope{ .base = Scope{
.id = Id.Root, .id = .Root,
.parent = null, .parent = null,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -155,7 +154,7 @@ pub const Scope = struct {
.base = undefined, .base = undefined,
.tree = tree, .tree = tree,
}; };
self.base.init(Id.AstTree, &root_scope.base); self.base.init(.AstTree, &root_scope.base);
return self; return self;
} }
@ -186,7 +185,7 @@ pub const Scope = struct {
.base = undefined, .base = undefined,
.table = event.RwLocked(Decl.Table).init(Decl.Table.init(comp.gpa())), .table = event.RwLocked(Decl.Table).init(Decl.Table.init(comp.gpa())),
}; };
self.base.init(Id.Decls, parent); self.base.init(.Decls, parent);
return self; return self;
} }
@ -219,15 +218,15 @@ pub const Scope = struct {
fn get(self: Safety, comp: *Compilation) bool { fn get(self: Safety, comp: *Compilation) bool {
return switch (self) { return switch (self) {
Safety.Auto => switch (comp.build_mode) { .Auto => switch (comp.build_mode) {
builtin.Mode.Debug, .Debug,
builtin.Mode.ReleaseSafe, .ReleaseSafe,
=> true, => true,
builtin.Mode.ReleaseFast, .ReleaseFast,
builtin.Mode.ReleaseSmall, .ReleaseSmall,
=> false, => false,
}, },
@TagType(Safety).Manual => |man| man.enabled, .Manual => |man| man.enabled,
}; };
} }
}; };
@ -243,7 +242,7 @@ pub const Scope = struct {
.is_comptime = undefined, .is_comptime = undefined,
.safety = Safety.Auto, .safety = Safety.Auto,
}; };
self.base.init(Id.Block, parent); self.base.init(.Block, parent);
return self; return self;
} }
@ -266,7 +265,7 @@ pub const Scope = struct {
.base = undefined, .base = undefined,
.fn_val = null, .fn_val = null,
}; };
self.base.init(Id.FnDef, parent); self.base.init(.FnDef, parent);
return self; return self;
} }
@ -282,7 +281,7 @@ pub const Scope = struct {
pub fn create(comp: *Compilation, parent: *Scope) !*CompTime { pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
const self = try comp.gpa().create(CompTime); const self = try comp.gpa().create(CompTime);
self.* = CompTime{ .base = undefined }; self.* = CompTime{ .base = undefined };
self.base.init(Id.CompTime, parent); self.base.init(.CompTime, parent);
return self; return self;
} }
@ -314,7 +313,7 @@ pub const Scope = struct {
.defer_expr_scope = defer_expr_scope, .defer_expr_scope = defer_expr_scope,
.kind = kind, .kind = kind,
}; };
self.base.init(Id.Defer, parent); self.base.init(.Defer, parent);
defer_expr_scope.base.ref(); defer_expr_scope.base.ref();
return self; return self;
} }
@ -338,7 +337,7 @@ pub const Scope = struct {
.expr_node = expr_node, .expr_node = expr_node,
.reported_err = false, .reported_err = false,
}; };
self.base.init(Id.DeferExpr, parent); self.base.init(.DeferExpr, parent);
return self; return self;
} }
@ -404,14 +403,14 @@ pub const Scope = struct {
.src_node = src_node, .src_node = src_node,
.data = undefined, .data = undefined,
}; };
self.base.init(Id.Var, parent); self.base.init(.Var, parent);
return self; return self;
} }
pub fn destroy(self: *Var, comp: *Compilation) void { pub fn destroy(self: *Var, comp: *Compilation) void {
switch (self.data) { switch (self.data) {
Data.Param => {}, .Param => {},
Data.Const => |value| value.deref(comp), .Const => |value| value.deref(comp),
} }
comp.gpa().destroy(self); comp.gpa().destroy(self);
} }

View File

@ -1,7 +1,6 @@
// This is Zig code that is used by both stage1 and stage2. // This is Zig code that is used by both stage1 and stage2.
// The prototypes in src/userland.h must match these definitions. // The prototypes in src/userland.h must match these definitions.
const builtin = @import("builtin");
const std = @import("std"); const std = @import("std");
const io = std.io; const io = std.io;
const mem = std.mem; const mem = std.mem;
@ -358,9 +357,9 @@ fn printErrMsgToFile(
color: errmsg.Color, color: errmsg.Color,
) !void { ) !void {
const color_on = switch (color) { const color_on = switch (color) {
errmsg.Color.Auto => file.isTty(), .Auto => file.isTty(),
errmsg.Color.On => true, .On => true,
errmsg.Color.Off => false, .Off => false,
}; };
const lok_token = parse_error.loc(); const lok_token = parse_error.loc();
const span = errmsg.Span{ const span = errmsg.Span{
@ -425,8 +424,8 @@ export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextRes
const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
return stage2_DepNextResult{ return stage2_DepNextResult{
.type_id = switch (token.id) { .type_id = switch (token.id) {
.target => stage2_DepNextResult.TypeId.target, .target => .target,
.prereq => stage2_DepNextResult.TypeId.prereq, .prereq => .prereq,
}, },
.textz = textz.toSlice().ptr, .textz = textz.toSlice().ptr,
}; };

View File

@ -1,6 +1,5 @@
const std = @import("std"); const std = @import("std");
const mem = std.mem; const mem = std.mem;
const builtin = @import("builtin");
const Target = std.Target; const Target = std.Target;
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
const introspect = @import("introspect.zig"); const introspect = @import("introspect.zig");
@ -45,7 +44,7 @@ pub const TestContext = struct {
errdefer self.zig_compiler.deinit(); errdefer self.zig_compiler.deinit();
self.group = std.event.Group(anyerror!void).init(allocator); self.group = std.event.Group(anyerror!void).init(allocator);
errdefer self.group.deinit(); errdefer self.group.wait();
self.zig_lib_dir = try introspect.resolveZigLibDir(allocator); self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);
errdefer allocator.free(self.zig_lib_dir); errdefer allocator.free(self.zig_lib_dir);
@ -95,7 +94,7 @@ pub const TestContext = struct {
file1_path, file1_path,
Target.Native, Target.Native,
Compilation.Kind.Obj, Compilation.Kind.Obj,
builtin.Mode.Debug, .Debug,
true, // is_static true, // is_static
self.zig_lib_dir, self.zig_lib_dir,
); );
@ -129,7 +128,7 @@ pub const TestContext = struct {
file1_path, file1_path,
Target.Native, Target.Native,
Compilation.Kind.Exe, Compilation.Kind.Exe,
builtin.Mode.Debug, .Debug,
false, false,
self.zig_lib_dir, self.zig_lib_dir,
); );
@ -154,7 +153,7 @@ pub const TestContext = struct {
const build_event = comp.events.get(); const build_event = comp.events.get();
switch (build_event) { switch (build_event) {
Compilation.Event.Ok => { .Ok => {
const argv = []const []const u8{exe_file_2}; const argv = []const []const u8{exe_file_2};
// TODO use event loop // TODO use event loop
const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024); const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
@ -172,8 +171,8 @@ pub const TestContext = struct {
return error.OutputMismatch; return error.OutputMismatch;
} }
}, },
Compilation.Event.Error => |err| return err, .Error => |err| return err,
Compilation.Event.Fail => |msgs| { .Fail => |msgs| {
var stderr = try std.io.getStdErr(); var stderr = try std.io.getStdErr();
try stderr.write("build incorrectly failed:\n"); try stderr.write("build incorrectly failed:\n");
for (msgs) |msg| { for (msgs) |msg| {
@ -196,13 +195,13 @@ pub const TestContext = struct {
const build_event = comp.events.get(); const build_event = comp.events.get();
switch (build_event) { switch (build_event) {
Compilation.Event.Ok => { .Ok => {
@panic("build incorrectly succeeded"); @panic("build incorrectly succeeded");
}, },
Compilation.Event.Error => |err| { .Error => |err| {
@panic("build incorrectly failed"); @panic("build incorrectly failed");
}, },
Compilation.Event.Fail => |msgs| { .Fail => |msgs| {
testing.expect(msgs.len != 0); testing.expect(msgs.len != 0);
for (msgs) |msg| { for (msgs) |msg| {
if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) { if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {

View File

@ -2,7 +2,6 @@
// and stage2. Currently the only way it is used is with `zig translate-c-2`. // and stage2. Currently the only way it is used is with `zig translate-c-2`.
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const ast = std.zig.ast; const ast = std.zig.ast;
const Token = std.zig.Token; const Token = std.zig.Token;
@ -14,7 +13,7 @@ pub const Mode = enum {
}; };
// TODO merge with Type.Fn.CallingConvention // TODO merge with Type.Fn.CallingConvention
const CallingConvention = builtin.TypeInfo.CallingConvention; const CallingConvention = std.builtin.TypeInfo.CallingConvention;
pub const ClangErrMsg = Stage2ErrorMsg; pub const ClangErrMsg = Stage2ErrorMsg;

View File

@ -1,5 +1,5 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = std.builtin;
const Scope = @import("scope.zig").Scope; const Scope = @import("scope.zig").Scope;
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
const Value = @import("value.zig").Value; const Value = @import("value.zig").Value;
@ -20,32 +20,32 @@ pub const Type = struct {
pub fn destroy(base: *Type, comp: *Compilation) void { pub fn destroy(base: *Type, comp: *Compilation) void {
switch (base.id) { switch (base.id) {
Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp), .Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp), .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp), .Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp), .Void => @fieldParentPtr(Void, "base", base).destroy(comp),
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp), .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp), .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp), .Int => @fieldParentPtr(Int, "base", base).destroy(comp),
Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp), .Float => @fieldParentPtr(Float, "base", base).destroy(comp),
Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp), .Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp), .Array => @fieldParentPtr(Array, "base", base).destroy(comp),
Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp), .ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp), .ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
Id.EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp), .EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp),
Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp), .Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp), .Null => @fieldParentPtr(Null, "base", base).destroy(comp),
Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp), .Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp), .ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp), .ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp), .Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp), .Union => @fieldParentPtr(Union, "base", base).destroy(comp),
Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp), .BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), .ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), .Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
Id.Frame => @fieldParentPtr(Frame, "base", base).destroy(comp), .Frame => @fieldParentPtr(Frame, "base", base).destroy(comp),
Id.AnyFrame => @fieldParentPtr(AnyFrame, "base", base).destroy(comp), .AnyFrame => @fieldParentPtr(AnyFrame, "base", base).destroy(comp),
Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp), .Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
} }
} }
@ -55,108 +55,108 @@ pub const Type = struct {
llvm_context: *llvm.Context, llvm_context: *llvm.Context,
) (error{OutOfMemory}!*llvm.Type) { ) (error{OutOfMemory}!*llvm.Type) {
switch (base.id) { switch (base.id) {
Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context), .Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context), .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
Id.Type => unreachable, .Type => unreachable,
Id.Void => unreachable, .Void => unreachable,
Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context), .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context),
Id.NoReturn => unreachable, .NoReturn => unreachable,
Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context), .Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context),
Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context), .Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context),
Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context), .Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context),
Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context), .Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context),
Id.ComptimeFloat => unreachable, .ComptimeFloat => unreachable,
Id.ComptimeInt => unreachable, .ComptimeInt => unreachable,
Id.EnumLiteral => unreachable, .EnumLiteral => unreachable,
Id.Undefined => unreachable, .Undefined => unreachable,
Id.Null => unreachable, .Null => unreachable,
Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context), .Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context),
Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context), .ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context),
Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context), .ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context),
Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context), .Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),
Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context), .Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),
Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context), .BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),
Id.ArgTuple => unreachable, .ArgTuple => unreachable,
Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), .Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
Id.Frame => return @fieldParentPtr(Frame, "base", base).getLlvmType(allocator, llvm_context), .Frame => return @fieldParentPtr(Frame, "base", base).getLlvmType(allocator, llvm_context),
Id.AnyFrame => return @fieldParentPtr(AnyFrame, "base", base).getLlvmType(allocator, llvm_context), .AnyFrame => return @fieldParentPtr(AnyFrame, "base", base).getLlvmType(allocator, llvm_context),
Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context), .Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
} }
} }
pub fn handleIsPtr(base: *Type) bool { pub fn handleIsPtr(base: *Type) bool {
switch (base.id) { switch (base.id) {
Id.Type, .Type,
Id.ComptimeFloat, .ComptimeFloat,
Id.ComptimeInt, .ComptimeInt,
Id.EnumLiteral, .EnumLiteral,
Id.Undefined, .Undefined,
Id.Null, .Null,
Id.BoundFn, .BoundFn,
Id.ArgTuple, .ArgTuple,
Id.Opaque, .Opaque,
=> unreachable, => unreachable,
Id.NoReturn, .NoReturn,
Id.Void, .Void,
Id.Bool, .Bool,
Id.Int, .Int,
Id.Float, .Float,
Id.Pointer, .Pointer,
Id.ErrorSet, .ErrorSet,
Id.Enum, .Enum,
Id.Fn, .Fn,
Id.Frame, .Frame,
Id.AnyFrame, .AnyFrame,
Id.Vector, .Vector,
=> return false, => return false,
Id.Struct => @panic("TODO"), .Struct => @panic("TODO"),
Id.Array => @panic("TODO"), .Array => @panic("TODO"),
Id.Optional => @panic("TODO"), .Optional => @panic("TODO"),
Id.ErrorUnion => @panic("TODO"), .ErrorUnion => @panic("TODO"),
Id.Union => @panic("TODO"), .Union => @panic("TODO"),
} }
} }
pub fn hasBits(base: *Type) bool { pub fn hasBits(base: *Type) bool {
switch (base.id) { switch (base.id) {
Id.Type, .Type,
Id.ComptimeFloat, .ComptimeFloat,
Id.ComptimeInt, .ComptimeInt,
Id.EnumLiteral, .EnumLiteral,
Id.Undefined, .Undefined,
Id.Null, .Null,
Id.BoundFn, .BoundFn,
Id.ArgTuple, .ArgTuple,
Id.Opaque, .Opaque,
=> unreachable, => unreachable,
Id.Void, .Void,
Id.NoReturn, .NoReturn,
=> return false, => return false,
Id.Bool, .Bool,
Id.Int, .Int,
Id.Float, .Float,
Id.Fn, .Fn,
Id.Frame, .Frame,
Id.AnyFrame, .AnyFrame,
Id.Vector, .Vector,
=> return true, => return true,
Id.Pointer => { .Pointer => {
const ptr_type = @fieldParentPtr(Pointer, "base", base); const ptr_type = @fieldParentPtr(Pointer, "base", base);
return ptr_type.key.child_type.hasBits(); return ptr_type.key.child_type.hasBits();
}, },
Id.ErrorSet => @panic("TODO"), .ErrorSet => @panic("TODO"),
Id.Enum => @panic("TODO"), .Enum => @panic("TODO"),
Id.Struct => @panic("TODO"), .Struct => @panic("TODO"),
Id.Array => @panic("TODO"), .Array => @panic("TODO"),
Id.Optional => @panic("TODO"), .Optional => @panic("TODO"),
Id.ErrorUnion => @panic("TODO"), .ErrorUnion => @panic("TODO"),
Id.Union => @panic("TODO"), .Union => @panic("TODO"),
} }
} }
@ -172,7 +172,7 @@ pub const Type = struct {
fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void { fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void {
base.* = Type{ base.* = Type{
.base = Value{ .base = Value{
.id = Value.Id.Type, .id = .Type,
.typ = &MetaType.get(comp).base, .typ = &MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -272,11 +272,11 @@ pub const Type = struct {
var result: u32 = 0; var result: u32 = 0;
result +%= hashAny(self.alignment, 0); result +%= hashAny(self.alignment, 0);
switch (self.data) { switch (self.data) {
Kind.Generic => |generic| { .Generic => |generic| {
result +%= hashAny(generic.param_count, 1); result +%= hashAny(generic.param_count, 1);
result +%= hashAny(generic.cc, 3); result +%= hashAny(generic.cc, 3);
}, },
Kind.Normal => |normal| { .Normal => |normal| {
result +%= hashAny(normal.return_type, 4); result +%= hashAny(normal.return_type, 4);
result +%= hashAny(normal.is_var_args, 5); result +%= hashAny(normal.is_var_args, 5);
result +%= hashAny(normal.cc, 6); result +%= hashAny(normal.cc, 6);
@ -294,14 +294,14 @@ pub const Type = struct {
if (self.alignment) |self_align| { if (self.alignment) |self_align| {
if (self_align != other.alignment.?) return false; if (self_align != other.alignment.?) return false;
} }
if (@TagType(Data)(self.data) != @TagType(Data)(other.data)) return false; if (self.data != other.data) return false;
switch (self.data) { switch (self.data) {
Kind.Generic => |*self_generic| { .Generic => |*self_generic| {
const other_generic = &other.data.Generic; const other_generic = &other.data.Generic;
if (self_generic.param_count != other_generic.param_count) return false; if (self_generic.param_count != other_generic.param_count) return false;
if (self_generic.cc != other_generic.cc) return false; if (self_generic.cc != other_generic.cc) return false;
}, },
Kind.Normal => |*self_normal| { .Normal => |*self_normal| {
const other_normal = &other.data.Normal; const other_normal = &other.data.Normal;
if (self_normal.cc != other_normal.cc) return false; if (self_normal.cc != other_normal.cc) return false;
if (self_normal.is_var_args != other_normal.is_var_args) return false; if (self_normal.is_var_args != other_normal.is_var_args) return false;
@ -318,8 +318,8 @@ pub const Type = struct {
pub fn deref(key: Key, comp: *Compilation) void { pub fn deref(key: Key, comp: *Compilation) void {
switch (key.data) { switch (key.data) {
Kind.Generic => {}, .Generic => {},
Kind.Normal => |normal| { .Normal => |normal| {
normal.return_type.base.deref(comp); normal.return_type.base.deref(comp);
for (normal.params) |param| { for (normal.params) |param| {
param.typ.base.deref(comp); param.typ.base.deref(comp);
@ -330,8 +330,8 @@ pub const Type = struct {
pub fn ref(key: Key) void { pub fn ref(key: Key) void {
switch (key.data) { switch (key.data) {
Kind.Generic => {}, .Generic => {},
Kind.Normal => |normal| { .Normal => |normal| {
normal.return_type.base.ref(); normal.return_type.base.ref();
for (normal.params) |param| { for (normal.params) |param| {
param.typ.base.ref(); param.typ.base.ref();
@ -361,8 +361,8 @@ pub const Type = struct {
pub fn paramCount(self: *Fn) usize { pub fn paramCount(self: *Fn) usize {
return switch (self.key.data) { return switch (self.key.data) {
Kind.Generic => |generic| generic.param_count, .Generic => |generic| generic.param_count,
Kind.Normal => |normal| normal.params.len, .Normal => |normal| normal.params.len,
}; };
} }
@ -396,7 +396,7 @@ pub const Type = struct {
const name_stream = &std.io.BufferOutStream.init(&name_buf).stream; const name_stream = &std.io.BufferOutStream.init(&name_buf).stream;
switch (key.data) { switch (key.data) {
Kind.Generic => |generic| { .Generic => |generic| {
self.non_key = NonKey{ .Generic = {} }; self.non_key = NonKey{ .Generic = {} };
const cc_str = ccFnTypeStr(generic.cc); const cc_str = ccFnTypeStr(generic.cc);
try name_stream.write(cc_str); try name_stream.write(cc_str);
@ -412,7 +412,7 @@ pub const Type = struct {
} }
try name_stream.write(" var"); try name_stream.write(" var");
}, },
Kind.Normal => |normal| { .Normal => |normal| {
self.non_key = NonKey{ self.non_key = NonKey{
.Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) }, .Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) },
}; };
@ -435,7 +435,7 @@ pub const Type = struct {
}, },
} }
self.base.init(comp, Id.Fn, name_buf.toOwnedSlice()); self.base.init(comp, .Fn, name_buf.toOwnedSlice());
{ {
const held = comp.fn_type_table.acquire(); const held = comp.fn_type_table.acquire();
@ -449,8 +449,8 @@ pub const Type = struct {
pub fn destroy(self: *Fn, comp: *Compilation) void { pub fn destroy(self: *Fn, comp: *Compilation) void {
self.key.deref(comp); self.key.deref(comp);
switch (self.key.data) { switch (self.key.data) {
Kind.Generic => {}, .Generic => {},
Kind.Normal => { .Normal => {
self.non_key.Normal.variable_list.deinit(); self.non_key.Normal.variable_list.deinit();
}, },
} }
@ -460,7 +460,7 @@ pub const Type = struct {
pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const normal = &self.key.data.Normal; const normal = &self.key.data.Normal;
const llvm_return_type = switch (normal.return_type.id) { const llvm_return_type = switch (normal.return_type.id) {
Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory, .Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
else => try normal.return_type.getLlvmType(allocator, llvm_context), else => try normal.return_type.getLlvmType(allocator, llvm_context),
}; };
const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len); const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
@ -588,7 +588,7 @@ pub const Type = struct {
const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count); const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count);
errdefer comp.gpa().free(name); errdefer comp.gpa().free(name);
self.base.init(comp, Id.Int, name); self.base.init(comp, .Int, name);
{ {
const held = comp.int_type_table.acquire(); const held = comp.int_type_table.acquire();
@ -650,8 +650,8 @@ pub const Type = struct {
pub fn hash(self: *const Key) u32 { pub fn hash(self: *const Key) u32 {
var result: u32 = 0; var result: u32 = 0;
result +%= switch (self.alignment) { result +%= switch (self.alignment) {
Align.Abi => 0xf201c090, .Abi => 0xf201c090,
Align.Override => |x| hashAny(x, 0), .Override => |x| hashAny(x, 0),
}; };
result +%= hashAny(self.child_type, 1); result +%= hashAny(self.child_type, 1);
result +%= hashAny(self.mut, 2); result +%= hashAny(self.mut, 2);
@ -670,8 +670,8 @@ pub const Type = struct {
return false; return false;
} }
switch (self.alignment) { switch (self.alignment) {
Align.Abi => return true, .Abi => return true,
Align.Override => |x| return x == other.alignment.Override, .Override => |x| return x == other.alignment.Override,
} }
} }
}; };
@ -714,8 +714,8 @@ pub const Type = struct {
pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 { pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
switch (self.key.alignment) { switch (self.key.alignment) {
Align.Abi => return self.key.child_type.getAbiAlignment(comp), .Abi => return self.key.child_type.getAbiAlignment(comp),
Align.Override => |alignment| return alignment, .Override => |alignment| return alignment,
} }
} }
@ -725,11 +725,11 @@ pub const Type = struct {
) !*Pointer { ) !*Pointer {
var normal_key = key; var normal_key = key;
switch (key.alignment) { switch (key.alignment) {
Align.Abi => {}, .Abi => {},
Align.Override => |alignment| { .Override => |alignment| {
const abi_align = try key.child_type.getAbiAlignment(comp); const abi_align = try key.child_type.getAbiAlignment(comp);
if (abi_align == alignment) { if (abi_align == alignment) {
normal_key.alignment = Align.Abi; normal_key.alignment = .Abi;
} }
}, },
} }
@ -752,21 +752,21 @@ pub const Type = struct {
errdefer comp.gpa().destroy(self); errdefer comp.gpa().destroy(self);
const size_str = switch (self.key.size) { const size_str = switch (self.key.size) {
Size.One => "*", .One => "*",
Size.Many => "[*]", .Many => "[*]",
Size.Slice => "[]", .Slice => "[]",
Size.C => "[*c]", .C => "[*c]",
}; };
const mut_str = switch (self.key.mut) { const mut_str = switch (self.key.mut) {
Mut.Const => "const ", .Const => "const ",
Mut.Mut => "", .Mut => "",
}; };
const vol_str = switch (self.key.vol) { const vol_str = switch (self.key.vol) {
Vol.Volatile => "volatile ", .Volatile => "volatile ",
Vol.Non => "", .Non => "",
}; };
const name = switch (self.key.alignment) { const name = switch (self.key.alignment) {
Align.Abi => try std.fmt.allocPrint( .Abi => try std.fmt.allocPrint(
comp.gpa(), comp.gpa(),
"{}{}{}{}", "{}{}{}{}",
size_str, size_str,
@ -774,7 +774,7 @@ pub const Type = struct {
vol_str, vol_str,
self.key.child_type.name, self.key.child_type.name,
), ),
Align.Override => |alignment| try std.fmt.allocPrint( .Override => |alignment| try std.fmt.allocPrint(
comp.gpa(), comp.gpa(),
"{}align<{}> {}{}{}", "{}align<{}> {}{}{}",
size_str, size_str,
@ -786,7 +786,7 @@ pub const Type = struct {
}; };
errdefer comp.gpa().free(name); errdefer comp.gpa().free(name);
self.base.init(comp, Id.Pointer, name); self.base.init(comp, .Pointer, name);
{ {
const held = comp.ptr_type_table.acquire(); const held = comp.ptr_type_table.acquire();
@ -854,7 +854,7 @@ pub const Type = struct {
const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name); const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
errdefer comp.gpa().free(name); errdefer comp.gpa().free(name);
self.base.init(comp, Id.Array, name); self.base.init(comp, .Array, name);
{ {
const held = comp.array_type_table.acquire(); const held = comp.array_type_table.acquire();
@ -1054,7 +1054,7 @@ pub const Type = struct {
fn hashAny(x: var, comptime seed: u64) u32 { fn hashAny(x: var, comptime seed: u64) u32 {
switch (@typeInfo(@typeOf(x))) { switch (@typeInfo(@typeOf(x))) {
builtin.TypeId.Int => |info| { .Int => |info| {
comptime var rng = comptime std.rand.DefaultPrng.init(seed); comptime var rng = comptime std.rand.DefaultPrng.init(seed);
const unsigned_x = @bitCast(@IntType(false, info.bits), x); const unsigned_x = @bitCast(@IntType(false, info.bits), x);
if (info.bits <= 32) { if (info.bits <= 32) {
@ -1063,21 +1063,21 @@ fn hashAny(x: var, comptime seed: u64) u32 {
return @truncate(u32, unsigned_x *% comptime rng.random.scalar(@typeOf(unsigned_x))); return @truncate(u32, unsigned_x *% comptime rng.random.scalar(@typeOf(unsigned_x)));
} }
}, },
builtin.TypeId.Pointer => |info| { .Pointer => |info| {
switch (info.size) { switch (info.size) {
builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed), .One => return hashAny(@ptrToInt(x), seed),
builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"), .Many => @compileError("implement hash function"),
builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"), .Slice => @compileError("implement hash function"),
builtin.TypeInfo.Pointer.Size.C => unreachable, .C => unreachable,
} }
}, },
builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed), .Enum => return hashAny(@enumToInt(x), seed),
builtin.TypeId.Bool => { .Bool => {
comptime var rng = comptime std.rand.DefaultPrng.init(seed); comptime var rng = comptime std.rand.DefaultPrng.init(seed);
const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) }; const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) };
return vals[@boolToInt(x)]; return vals[@boolToInt(x)];
}, },
builtin.TypeId.Optional => { .Optional => {
if (x) |non_opt| { if (x) |non_opt| {
return hashAny(non_opt, seed); return hashAny(non_opt, seed);
} else { } else {

View File

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
const Scope = @import("scope.zig").Scope; const Scope = @import("scope.zig").Scope;
const Compilation = @import("compilation.zig").Compilation; const Compilation = @import("compilation.zig").Compilation;
const ObjectFile = @import("codegen.zig").ObjectFile; const ObjectFile = @import("codegen.zig").ObjectFile;
@ -24,15 +23,15 @@ pub const Value = struct {
if (base.ref_count.decr() == 1) { if (base.ref_count.decr() == 1) {
base.typ.base.deref(comp); base.typ.base.deref(comp);
switch (base.id) { switch (base.id) {
Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp), .Type => @fieldParentPtr(Type, "base", base).destroy(comp),
Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp), .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
Id.FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp), .FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp),
Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp), .Void => @fieldParentPtr(Void, "base", base).destroy(comp),
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp), .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp), .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp), .Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp), .Int => @fieldParentPtr(Int, "base", base).destroy(comp),
Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp), .Array => @fieldParentPtr(Array, "base", base).destroy(comp),
} }
} }
} }
@ -59,15 +58,15 @@ pub const Value = struct {
pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) { pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
switch (base.id) { switch (base.id) {
Id.Type => unreachable, .Type => unreachable,
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile), .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
Id.FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile), .FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile),
Id.Void => return null, .Void => return null,
Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile), .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),
Id.NoReturn => unreachable, .NoReturn => unreachable,
Id.Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile), .Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile),
Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile), .Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile),
Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile), .Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile),
} }
} }
@ -83,15 +82,15 @@ pub const Value = struct {
pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) { pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
switch (base.id) { switch (base.id) {
Id.Type => unreachable, .Type => unreachable,
Id.Fn => unreachable, .Fn => unreachable,
Id.FnProto => unreachable, .FnProto => unreachable,
Id.Void => unreachable, .Void => unreachable,
Id.Bool => unreachable, .Bool => unreachable,
Id.NoReturn => unreachable, .NoReturn => unreachable,
Id.Ptr => unreachable, .Ptr => unreachable,
Id.Array => unreachable, .Array => unreachable,
Id.Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base, .Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base,
} }
} }
@ -138,7 +137,7 @@ pub const Value = struct {
const self = try comp.gpa().create(FnProto); const self = try comp.gpa().create(FnProto);
self.* = FnProto{ self.* = FnProto{
.base = Value{ .base = Value{
.id = Value.Id.FnProto, .id = .FnProto,
.typ = &fn_type.base, .typ = &fn_type.base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -202,7 +201,7 @@ pub const Value = struct {
const self = try comp.gpa().create(Fn); const self = try comp.gpa().create(Fn);
self.* = Fn{ self.* = Fn{
.base = Value{ .base = Value{
.id = Value.Id.Fn, .id = .Fn,
.typ = &fn_type.base, .typ = &fn_type.base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -359,7 +358,7 @@ pub const Value = struct {
const self = try comp.gpa().create(Value.Ptr); const self = try comp.gpa().create(Value.Ptr);
self.* = Value.Ptr{ self.* = Value.Ptr{
.base = Value{ .base = Value{
.id = Value.Id.Ptr, .id = .Ptr,
.typ = &ptr_type.base, .typ = &ptr_type.base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -385,8 +384,8 @@ pub const Value = struct {
const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context); const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
// TODO carefully port the logic from codegen.cpp:gen_const_val_ptr // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
switch (self.special) { switch (self.special) {
Special.Scalar => |scalar| @panic("TODO"), .Scalar => |scalar| @panic("TODO"),
Special.BaseArray => |base_array| { .BaseArray => |base_array| {
// TODO put this in one .o file only, and after that, generate extern references to it // TODO put this in one .o file only, and after that, generate extern references to it
const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?; const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
const ptr_bit_count = ofile.comp.target_ptr_bits; const ptr_bit_count = ofile.comp.target_ptr_bits;
@ -401,9 +400,9 @@ pub const Value = struct {
@intCast(c_uint, indices.len), @intCast(c_uint, indices.len),
) orelse return error.OutOfMemory; ) orelse return error.OutOfMemory;
}, },
Special.BaseStruct => |base_struct| @panic("TODO"), .BaseStruct => |base_struct| @panic("TODO"),
Special.HardCodedAddr => |addr| @panic("TODO"), .HardCodedAddr => |addr| @panic("TODO"),
Special.Discard => unreachable, .Discard => unreachable,
} }
} }
}; };
@ -437,7 +436,7 @@ pub const Value = struct {
const self = try comp.gpa().create(Value.Array); const self = try comp.gpa().create(Value.Array);
self.* = Value.Array{ self.* = Value.Array{
.base = Value{ .base = Value{
.id = Value.Id.Array, .id = .Array,
.typ = &array_type.base, .typ = &array_type.base,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -450,22 +449,22 @@ pub const Value = struct {
pub fn destroy(self: *Array, comp: *Compilation) void { pub fn destroy(self: *Array, comp: *Compilation) void {
switch (self.special) { switch (self.special) {
Special.Undefined => {}, .Undefined => {},
Special.OwnedBuffer => |buf| { .OwnedBuffer => |buf| {
comp.gpa().free(buf); comp.gpa().free(buf);
}, },
Special.Explicit => {}, .Explicit => {},
} }
comp.gpa().destroy(self); comp.gpa().destroy(self);
} }
pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value { pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
switch (self.special) { switch (self.special) {
Special.Undefined => { .Undefined => {
const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
return llvm.GetUndef(llvm_type); return llvm.GetUndef(llvm_type);
}, },
Special.OwnedBuffer => |buf| { .OwnedBuffer => |buf| {
const dont_null_terminate = 1; const dont_null_terminate = 1;
const llvm_str_init = llvm.ConstStringInContext( const llvm_str_init = llvm.ConstStringInContext(
ofile.context, ofile.context,
@ -482,7 +481,7 @@ pub const Value = struct {
llvm.SetAlignment(global, llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, str_init_type)); llvm.SetAlignment(global, llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, str_init_type));
return global; return global;
}, },
Special.Explicit => @panic("TODO"), .Explicit => @panic("TODO"),
} }
//{ //{
@ -517,7 +516,7 @@ pub const Value = struct {
const self = try comp.gpa().create(Value.Int); const self = try comp.gpa().create(Value.Int);
self.* = Value.Int{ self.* = Value.Int{
.base = Value{ .base = Value{
.id = Value.Id.Int, .id = .Int,
.typ = typ, .typ = typ,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },
@ -536,7 +535,7 @@ pub const Value = struct {
pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value { pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
switch (self.base.typ.id) { switch (self.base.typ.id) {
Type.Id.Int => { .Int => {
const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context); const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
if (self.big_int.len() == 0) { if (self.big_int.len() == 0) {
return llvm.ConstNull(type_ref); return llvm.ConstNull(type_ref);
@ -554,7 +553,7 @@ pub const Value = struct {
}; };
return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val); return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);
}, },
Type.Id.ComptimeInt => unreachable, .ComptimeInt => unreachable,
else => unreachable, else => unreachable,
} }
} }
@ -566,7 +565,7 @@ pub const Value = struct {
const new = try comp.gpa().create(Value.Int); const new = try comp.gpa().create(Value.Int);
new.* = Value.Int{ new.* = Value.Int{
.base = Value{ .base = Value{
.id = Value.Id.Int, .id = .Int,
.typ = old.base.typ, .typ = old.base.typ,
.ref_count = std.atomic.Int(usize).init(1), .ref_count = std.atomic.Int(usize).init(1),
}, },