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 {
tag: Tag,
pub const all_types = .{
Constant,
PtrToInt,
FieldPtr,
Deref,
Assembly,
Unreach,
Fn,
};
/// These names are used for the IR text format.
pub const Tag = enum {
constant,
@ -29,6 +19,23 @@ pub const Inst = struct {
@"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,
/// 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.
@ -45,7 +52,9 @@ pub const Inst = struct {
pub const PtrToInt = struct {
base: Inst = Inst{ .tag = .ptrtoint },
positionals: struct {},
positionals: struct {
ptr: OtherInst,
},
kw_args: struct {},
};
@ -224,10 +233,10 @@ fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, Par
else => {},
}
const fn_name = try skipToAndOver(ctx, '(');
inline for (Inst.all_types) |InstType| {
const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag);
if (mem.eql(u8, this_name, fn_name)) {
return parseInstructionGeneric(ctx, this_name, InstType, opt_type);
inline for (@typeInfo(Inst.Tag).Enum.fields) |field| {
if (mem.eql(u8, field.name, fn_name)) {
const tag = @field(Inst.Tag, field.name);
return parseInstructionGeneric(ctx, field.name, Inst.TagToType(tag), opt_type);
}
}
return parseError(ctx, "unknown instruction '{}'", .{fn_name});
@ -288,6 +297,9 @@ fn parseParameterGeneric(ctx: *ParseContext, comptime T: type) !T {
}
switch (T) {
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", .{}),
else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
}