stage2: hook up Zig AST to ZIR

* Introduce the concept of anonymous Decls
 * Primitive Hello, World with inline asm works
 * There is still an unsolved problem of how to manage ZIR instructions
   memory when generating from AST. Currently it leaks.
This commit is contained in:
Andrew Kelley 2020-06-11 01:22:07 -04:00
parent 4a38799631
commit b4eac0414a
5 changed files with 980 additions and 191 deletions

View File

@ -1,4 +1,6 @@
const std = @import("std.zig");
const tokenizer = @import("zig/tokenizer.zig");
pub const Token = tokenizer.Token;
pub const Tokenizer = tokenizer.Tokenizer;
pub const parse = @import("zig/parse.zig").parse;
@ -9,6 +11,21 @@ pub const ast = @import("zig/ast.zig");
pub const system = @import("zig/system.zig");
pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget;
pub const SrcHash = [16]u8;
/// If the source is small enough, it is used directly as the hash.
/// If it is long, blake3 hash is computed.
pub fn hashSrc(src: []const u8) SrcHash {
var out: SrcHash = undefined;
if (src.len <= SrcHash.len) {
std.mem.copy(u8, &out, src);
std.mem.set(u8, out[src.len..], 0);
} else {
std.crypto.Blake3.hash(src, &out);
}
return out;
}
pub fn findLineColumn(source: []const u8, byte_offset: usize) struct { line: usize, column: usize } {
var line: usize = 0;
var column: usize = 0;

File diff suppressed because it is too large Load Diff

View File

@ -86,7 +86,7 @@ const usage_build_generic =
\\ zig build-obj <options> [files]
\\
\\Supported file types:
\\ (planned) .zig Zig source code
\\ .zig Zig source code
\\ .zir Zig Intermediate Representation code
\\ (planned) .o ELF object file
\\ (planned) .o MACH-O (macOS) object file

View File

@ -78,8 +78,8 @@ pub const Value = extern union {
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
};
pub fn initTag(comptime small_tag: Tag) Value {
comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
pub fn initTag(small_tag: Tag) Value {
assert(@enumToInt(small_tag) < Tag.no_payload_count);
return .{ .tag_if_small_enough = @enumToInt(small_tag) };
}

View File

@ -14,20 +14,24 @@ const IrModule = @import("Module.zig");
/// These are instructions that correspond to the ZIR text format. See `ir.Inst` for
/// in-memory, analyzed instructions with types and values.
/// TODO Separate into Decl and Inst. Decl will have extra fields, and will make the
/// undefined default field value of contents_hash no longer needed.
pub const Inst = struct {
tag: Tag,
/// Byte offset into the source.
src: usize,
name: []const u8,
/// Slice into the source of the part after the = and before the next instruction.
contents: []const u8 = &[0]u8{},
/// Hash of slice into the source of the part after the = and before the next instruction.
contents_hash: std.zig.SrcHash = undefined,
/// These names are used directly as the instruction names in the text format.
pub const Tag = enum {
breakpoint,
call,
compileerror,
/// Special case, has no textual representation.
@"const",
/// Represents a pointer to a global decl by name.
declref,
/// The syntax `@foo` is equivalent to `declval("foo")`.
@ -43,10 +47,10 @@ pub const Inst = struct {
@"unreachable",
@"return",
@"fn",
fntype,
@"export",
primitive,
ref,
fntype,
intcast,
bitcast,
elemptr,
@ -64,6 +68,7 @@ pub const Inst = struct {
.declref => DeclRef,
.declval => DeclVal,
.compileerror => CompileError,
.@"const" => Const,
.str => Str,
.int => Int,
.ptrtoint => PtrToInt,
@ -147,6 +152,16 @@ pub const Inst = struct {
kw_args: struct {},
};
pub const Const = struct {
pub const base_tag = Tag.@"const";
base: Inst,
positionals: struct {
typed_value: TypedValue,
},
kw_args: struct {},
};
pub const Str = struct {
pub const base_tag = Tag.str;
base: Inst,
@ -253,6 +268,19 @@ pub const Inst = struct {
kw_args: struct {},
};
pub const FnType = struct {
pub const base_tag = Tag.fntype;
base: Inst,
positionals: struct {
param_types: []*Inst,
return_type: *Inst,
},
kw_args: struct {
cc: std.builtin.CallingConvention = .Unspecified,
},
};
pub const Export = struct {
pub const base_tag = Tag.@"export";
base: Inst,
@ -348,19 +376,6 @@ pub const Inst = struct {
};
};
pub const FnType = struct {
pub const base_tag = Tag.fntype;
base: Inst,
positionals: struct {
param_types: []*Inst,
return_type: *Inst,
},
kw_args: struct {
cc: std.builtin.CallingConvention = .Unspecified,
},
};
pub const IntCast = struct {
pub const base_tag = Tag.intcast;
base: Inst,
@ -526,6 +541,7 @@ pub const Module = struct {
.declref => return self.writeInstToStreamGeneric(stream, .declref, decl, inst_table),
.declval => return self.writeInstToStreamGeneric(stream, .declval, decl, inst_table),
.compileerror => return self.writeInstToStreamGeneric(stream, .compileerror, decl, inst_table),
.@"const" => return self.writeInstToStreamGeneric(stream, .@"const", decl, inst_table),
.str => return self.writeInstToStreamGeneric(stream, .str, decl, inst_table),
.int => return self.writeInstToStreamGeneric(stream, .int, decl, inst_table),
.ptrtoint => return self.writeInstToStreamGeneric(stream, .ptrtoint, decl, inst_table),
@ -619,6 +635,7 @@ pub const Module = struct {
bool => return stream.writeByte("01"[@boolToInt(param)]),
[]u8, []const u8 => return std.zig.renderStringLiteral(param, stream),
BigIntConst => return stream.print("{}", .{param}),
TypedValue => unreachable, // this is a special case
else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
}
}
@ -929,7 +946,7 @@ const Parser = struct {
}
try requireEatBytes(self, ")");
inst_specific.base.contents = self.source[contents_start..self.i];
inst_specific.base.contents_hash = std.zig.hashSrc(self.source[contents_start..self.i]);
//std.debug.warn("parsed {} = '{}'\n", .{ inst_specific.base.name, inst_specific.base.contents });
return &inst_specific.base;
@ -978,6 +995,7 @@ const Parser = struct {
*Inst => return parseParameterInst(self, body_ctx),
[]u8, []const u8 => return self.parseStringLiteral(),
BigIntConst => return self.parseIntegerLiteral(),
TypedValue => return self.fail("'const' is a special instruction; not legal in ZIR text", .{}),
else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
}
return self.fail("TODO parse parameter {}", .{@typeName(T)});