ir: more foolproof way to organize instruction parsing

master
Andrew Kelley 2020-04-19 00:15:52 -04:00
parent 4cb203db92
commit 49e2f3ca36
1 changed files with 27 additions and 15 deletions

View File

@ -8,16 +8,6 @@ const assert = std.debug.assert;
pub const Inst = struct { pub const Inst = struct {
tag: Tag, tag: Tag,
pub const all_types = .{
Constant,
PtrToInt,
FieldPtr,
Deref,
Assembly,
Unreach,
Fn,
};
/// These names are used for the IR text format. /// These names are used for the IR text format.
pub const Tag = enum { pub const Tag = enum {
constant, constant,
@ -29,6 +19,23 @@ pub const Inst = struct {
@"fn", @"fn",
}; };
pub fn TagToType(tag: Tag) type {
return switch (tag) {
.constant => Constant,
.ptrtoint => PtrToInt,
.fieldptr => FieldPtr,
.deref => Deref,
.@"asm" => Assembly,
.unreach => Unreach,
.@"fn" => Fn,
};
}
/// Represents a reference to another instruction.
pub const OtherInst = struct {
index: usize,
};
/// This struct owns the `Value` memory. When the struct is deallocated, /// This struct owns the `Value` memory. When the struct is deallocated,
/// so is the `Value`. The value of a constant must be copied into /// so is the `Value`. The value of a constant must be copied into
/// a memory location for the value to survive after a const instruction. /// a memory location for the value to survive after a const instruction.
@ -45,7 +52,9 @@ pub const Inst = struct {
pub const PtrToInt = struct { pub const PtrToInt = struct {
base: Inst = Inst{ .tag = .ptrtoint }, base: Inst = Inst{ .tag = .ptrtoint },
positionals: struct {}, positionals: struct {
ptr: OtherInst,
},
kw_args: struct {}, kw_args: struct {},
}; };
@ -224,10 +233,10 @@ fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, Par
else => {}, else => {},
} }
const fn_name = try skipToAndOver(ctx, '('); const fn_name = try skipToAndOver(ctx, '(');
inline for (Inst.all_types) |InstType| { inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag); if (mem.eql(u8, field.name, fn_name)) {
if (mem.eql(u8, this_name, fn_name)) { const tag = @field(Inst.Tag, field.name);
return parseInstructionGeneric(ctx, this_name, InstType, opt_type); return parseInstructionGeneric(ctx, field.name, Inst.TagToType(tag), opt_type);
} }
} }
return parseError(ctx, "unknown instruction '{}'", .{fn_name}); return parseError(ctx, "unknown instruction '{}'", .{fn_name});
@ -288,6 +297,9 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
} }
switch (T) { switch (T) {
Inst.Fn.Body => return parseBody(ctx), Inst.Fn.Body => return parseBody(ctx),
Inst.OtherInst => {
return parseError(ctx, "TODO implement parseParameterGeneric for OtherInst", .{});
},
Value => return parseError(ctx, "TODO implement parseParameterGeneric for type Value", .{}), Value => return parseError(ctx, "TODO implement parseParameterGeneric for type Value", .{}),
else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)), else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
} }