stage2: first pass over Module.zig for AIR memory layout
This commit is contained in:
359
src/Module.zig
359
src/Module.zig
@@ -1155,7 +1155,7 @@ pub const Scope = struct {
|
||||
/// This can vary during inline or comptime function calls. See `Sema.owner_decl`
|
||||
/// for the one that will be the same for all Block instances.
|
||||
src_decl: *Decl,
|
||||
instructions: ArrayListUnmanaged(*ir.Inst),
|
||||
instructions: ArrayListUnmanaged(Air.Inst.Index),
|
||||
label: ?*Label = null,
|
||||
inlining: ?*Inlining,
|
||||
/// If runtime_index is not 0 then one of these is guaranteed to be non null.
|
||||
@@ -1187,14 +1187,14 @@ pub const Scope = struct {
|
||||
};
|
||||
|
||||
pub const Merges = struct {
|
||||
block_inst: *ir.Inst.Block,
|
||||
block_inst: Air.Inst.Index,
|
||||
/// Separate array list from break_inst_list so that it can be passed directly
|
||||
/// to resolvePeerTypes.
|
||||
results: ArrayListUnmanaged(*ir.Inst),
|
||||
results: ArrayListUnmanaged(Air.Inst.Index),
|
||||
/// Keeps track of the break instructions so that the operand can be replaced
|
||||
/// if we need to add type coercion at the end of block analysis.
|
||||
/// Same indexes, capacity, length as `results`.
|
||||
br_list: ArrayListUnmanaged(*ir.Inst.Br),
|
||||
br_list: ArrayListUnmanaged(Air.Inst.Index),
|
||||
};
|
||||
|
||||
/// For debugging purposes.
|
||||
@@ -1230,187 +1230,6 @@ pub const Scope = struct {
|
||||
pub fn getFileScope(block: *Block) *Scope.File {
|
||||
return block.src_decl.namespace.file_scope;
|
||||
}
|
||||
|
||||
pub fn addNoOp(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ty: Type,
|
||||
comptime tag: ir.Inst.Tag,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(tag.Type());
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = tag,
|
||||
.ty = ty,
|
||||
.src = src,
|
||||
},
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addUnOp(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ty: Type,
|
||||
tag: ir.Inst.Tag,
|
||||
operand: *ir.Inst,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.UnOp);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = tag,
|
||||
.ty = ty,
|
||||
.src = src,
|
||||
},
|
||||
.operand = operand,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addBinOp(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ty: Type,
|
||||
tag: ir.Inst.Tag,
|
||||
lhs: *ir.Inst,
|
||||
rhs: *ir.Inst,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.BinOp);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = tag,
|
||||
.ty = ty,
|
||||
.src = src,
|
||||
},
|
||||
.lhs = lhs,
|
||||
.rhs = rhs,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addBr(
|
||||
scope_block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
target_block: *ir.Inst.Block,
|
||||
operand: *ir.Inst,
|
||||
) !*ir.Inst.Br {
|
||||
const inst = try scope_block.sema.arena.create(ir.Inst.Br);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = .br,
|
||||
.ty = Type.initTag(.noreturn),
|
||||
.src = src,
|
||||
},
|
||||
.operand = operand,
|
||||
.block = target_block,
|
||||
};
|
||||
try scope_block.instructions.append(scope_block.sema.gpa, &inst.base);
|
||||
return inst;
|
||||
}
|
||||
|
||||
pub fn addCondBr(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
condition: *ir.Inst,
|
||||
then_body: ir.Body,
|
||||
else_body: ir.Body,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.CondBr);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = .condbr,
|
||||
.ty = Type.initTag(.noreturn),
|
||||
.src = src,
|
||||
},
|
||||
.condition = condition,
|
||||
.then_body = then_body,
|
||||
.else_body = else_body,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addCall(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ty: Type,
|
||||
func: *ir.Inst,
|
||||
args: []const *ir.Inst,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.Call);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = .call,
|
||||
.ty = ty,
|
||||
.src = src,
|
||||
},
|
||||
.func = func,
|
||||
.args = args,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addSwitchBr(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
operand: *ir.Inst,
|
||||
cases: []ir.Inst.SwitchBr.Case,
|
||||
else_body: ir.Body,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.SwitchBr);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = .switchbr,
|
||||
.ty = Type.initTag(.noreturn),
|
||||
.src = src,
|
||||
},
|
||||
.target = operand,
|
||||
.cases = cases,
|
||||
.else_body = else_body,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, line: u32, column: u32) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.DbgStmt);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = .dbg_stmt,
|
||||
.ty = Type.initTag(.void),
|
||||
.src = src,
|
||||
},
|
||||
.line = line,
|
||||
.column = column,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
|
||||
pub fn addStructFieldPtr(
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
ty: Type,
|
||||
struct_ptr: *ir.Inst,
|
||||
field_index: u32,
|
||||
) !*ir.Inst {
|
||||
const inst = try block.sema.arena.create(ir.Inst.StructFieldPtr);
|
||||
inst.* = .{
|
||||
.base = .{
|
||||
.tag = .struct_field_ptr,
|
||||
.ty = ty,
|
||||
.src = src,
|
||||
},
|
||||
.struct_ptr = struct_ptr,
|
||||
.field_index = field_index,
|
||||
};
|
||||
try block.instructions.append(block.sema.gpa, &inst.base);
|
||||
return &inst.base;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3594,30 +3413,14 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air {
|
||||
defer decl.value_arena.?.* = arena.state;
|
||||
|
||||
const fn_ty = decl.ty;
|
||||
const param_inst_list = try gpa.alloc(*ir.Inst, fn_ty.fnParamLen());
|
||||
const param_inst_list = try gpa.alloc(Air.Inst.Index, fn_ty.fnParamLen());
|
||||
defer gpa.free(param_inst_list);
|
||||
|
||||
for (param_inst_list) |*param_inst, param_index| {
|
||||
const param_type = fn_ty.fnParamType(param_index);
|
||||
const arg_inst = try arena.allocator.create(ir.Inst.Arg);
|
||||
arg_inst.* = .{
|
||||
.base = .{
|
||||
.tag = .arg,
|
||||
.ty = param_type,
|
||||
.src = .unneeded,
|
||||
},
|
||||
.name = undefined, // Set in the semantic analysis of the arg instruction.
|
||||
};
|
||||
param_inst.* = &arg_inst.base;
|
||||
}
|
||||
|
||||
const zir = decl.namespace.file_scope.zir;
|
||||
|
||||
var sema: Sema = .{
|
||||
.mod = mod,
|
||||
.gpa = gpa,
|
||||
.arena = &arena.allocator,
|
||||
.code = zir,
|
||||
.code = decl.namespace.file_scope.zir,
|
||||
.owner_decl = decl,
|
||||
.namespace = decl.namespace,
|
||||
.func = func,
|
||||
@@ -3641,7 +3444,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air {
|
||||
};
|
||||
defer inner_block.instructions.deinit(gpa);
|
||||
|
||||
// AIR currently requires the arg parameters to be the first N instructions
|
||||
// AIR requires the arg parameters to be the first N instructions.
|
||||
for (param_inst_list) |*param_inst, param_index| {
|
||||
const param_type = fn_ty.fnParamType(param_index);
|
||||
const ty_ref = try sema.addType(param_type);
|
||||
param_inst.* = @intCast(u32, sema.air_instructions.len);
|
||||
try sema.air_instructions.append(gpa, .{
|
||||
.tag = .arg,
|
||||
.data = .{
|
||||
.ty_str = .{
|
||||
.ty = ty_ref,
|
||||
.str = undefined, // Set in the semantic analysis of the arg instruction.
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
try inner_block.instructions.appendSlice(gpa, param_inst_list);
|
||||
|
||||
func.state = .in_progress;
|
||||
@@ -3650,17 +3467,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air {
|
||||
try sema.analyzeFnBody(&inner_block, func.zir_body_inst);
|
||||
|
||||
// Copy the block into place and mark that as the main block.
|
||||
sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = sema.air_extra.items.len;
|
||||
try sema.air_extra.appendSlice(inner_block.instructions.items);
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, inner_block.instructions.items.len + 1);
|
||||
const main_block_index = sema.addExtraAssumeCapacity(Air.Block{
|
||||
.body_len = @intCast(u32, inner_block.instructions.items.len),
|
||||
});
|
||||
sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
|
||||
sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index;
|
||||
|
||||
func.state = .success;
|
||||
log.debug("set {s} to success", .{decl.name});
|
||||
|
||||
return Air{
|
||||
.instructions = sema.air_instructions.toOwnedSlice(),
|
||||
.extra = sema.air_extra.toOwnedSlice(),
|
||||
.values = sema.air_values.toOwnedSlice(),
|
||||
.variables = sema.air_variables.toOwnedSlice(),
|
||||
.extra = sema.air_extra.toOwnedSlice(gpa),
|
||||
.values = sema.air_values.toOwnedSlice(gpa),
|
||||
.variables = sema.air_variables.toOwnedSlice(gpa),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3815,94 +3636,6 @@ pub fn analyzeExport(
|
||||
de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export;
|
||||
errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1);
|
||||
}
|
||||
pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst {
|
||||
_ = mod;
|
||||
const const_inst = try arena.create(ir.Inst.Constant);
|
||||
const_inst.* = .{
|
||||
.base = .{
|
||||
.tag = ir.Inst.Constant.base_tag,
|
||||
.ty = typed_value.ty,
|
||||
.src = src,
|
||||
},
|
||||
.val = typed_value.val,
|
||||
};
|
||||
return &const_inst.base;
|
||||
}
|
||||
|
||||
pub fn constType(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = try ty.toValue(arena),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constVoid(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = Type.initTag(.void),
|
||||
.val = Value.initTag(.void_value),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constNoReturn(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = Type.initTag(.noreturn),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constUndef(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = ty,
|
||||
.val = Value.initTag(.undef),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constBool(mod: *Module, arena: *Allocator, src: LazySrcLoc, v: bool) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = Type.initTag(.bool),
|
||||
.val = ([2]Value{ Value.initTag(.bool_false), Value.initTag(.bool_true) })[@boolToInt(v)],
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constIntUnsigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: u64) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = ty,
|
||||
.val = try Value.Tag.int_u64.create(arena, int),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constIntSigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: i64) !*ir.Inst {
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = ty,
|
||||
.val = try Value.Tag.int_i64.create(arena, int),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, big_int: BigIntConst) !*ir.Inst {
|
||||
if (big_int.positive) {
|
||||
if (big_int.to(u64)) |x| {
|
||||
return mod.constIntUnsigned(arena, src, ty, x);
|
||||
} else |err| switch (err) {
|
||||
error.NegativeIntoUnsigned => unreachable,
|
||||
error.TargetTooSmall => {}, // handled below
|
||||
}
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = ty,
|
||||
.val = try Value.Tag.int_big_positive.create(arena, big_int.limbs),
|
||||
});
|
||||
} else {
|
||||
if (big_int.to(i64)) |x| {
|
||||
return mod.constIntSigned(arena, src, ty, x);
|
||||
} else |err| switch (err) {
|
||||
error.NegativeIntoUnsigned => unreachable,
|
||||
error.TargetTooSmall => {}, // handled below
|
||||
}
|
||||
return mod.constInst(arena, src, .{
|
||||
.ty = ty,
|
||||
.val = try Value.Tag.int_big_negative.create(arena, big_int.limbs),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void {
|
||||
const scope_decl = scope.ownerDecl().?;
|
||||
@@ -4438,38 +4171,6 @@ pub fn errorUnionType(
|
||||
});
|
||||
}
|
||||
|
||||
pub fn dumpInst(mod: *Module, scope: *Scope, inst: *ir.Inst) void {
|
||||
const zir_module = scope.namespace();
|
||||
const source = zir_module.getSource(mod) catch @panic("dumpInst failed to get source");
|
||||
const loc = std.zig.findLineColumn(source, inst.src);
|
||||
if (inst.tag == .constant) {
|
||||
std.debug.print("constant ty={} val={} src={s}:{d}:{d}\n", .{
|
||||
inst.ty,
|
||||
inst.castTag(.constant).?.val,
|
||||
zir_module.subFilePath(),
|
||||
loc.line + 1,
|
||||
loc.column + 1,
|
||||
});
|
||||
} else if (inst.deaths == 0) {
|
||||
std.debug.print("{s} ty={} src={s}:{d}:{d}\n", .{
|
||||
@tagName(inst.tag),
|
||||
inst.ty,
|
||||
zir_module.subFilePath(),
|
||||
loc.line + 1,
|
||||
loc.column + 1,
|
||||
});
|
||||
} else {
|
||||
std.debug.print("{s} ty={} deaths={b} src={s}:{d}:{d}\n", .{
|
||||
@tagName(inst.tag),
|
||||
inst.ty,
|
||||
inst.deaths,
|
||||
zir_module.subFilePath(),
|
||||
loc.line + 1,
|
||||
loc.column + 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getTarget(mod: Module) Target {
|
||||
return mod.comp.bin_file.options.target;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user