mirror of
https://github.com/ziglang/zig.git
synced 2024-11-26 15:12:31 +00:00
let's make wasm codegen emit MIR
which is then lowered to wasm code during linking, with optimal function indexes etc, or relocations are emitted if outputting an object.
This commit is contained in:
parent
c4b2bdb12c
commit
12467ec721
@ -54,22 +54,19 @@ const WValue = union(enum) {
|
||||
float32: f32,
|
||||
/// A constant 64bit float value
|
||||
float64: f64,
|
||||
/// A value that represents a pointer to the data section
|
||||
/// Note: The value contains the symbol index, rather than the actual address
|
||||
/// as we use this to perform the relocation.
|
||||
memory: u32,
|
||||
/// A value that represents a pointer to the data section.
|
||||
memory: InternPool.Index,
|
||||
/// A value that represents a parent pointer and an offset
|
||||
/// from that pointer. i.e. when slicing with constant values.
|
||||
memory_offset: struct {
|
||||
/// The symbol of the parent pointer
|
||||
pointer: u32,
|
||||
pointer: InternPool.Index,
|
||||
/// Offset will be set as addend when relocating
|
||||
offset: u32,
|
||||
},
|
||||
/// Represents a function pointer
|
||||
/// In wasm function pointers are indexes into a function table,
|
||||
/// rather than an address in the data section.
|
||||
function_index: u32,
|
||||
function_index: InternPool.Index,
|
||||
/// Offset from the bottom of the virtual stack, with the offset
|
||||
/// pointing to where the value lives.
|
||||
stack_offset: struct {
|
||||
@ -775,13 +772,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
|
||||
// In the other cases, we will simply lower the constant to a value that fits
|
||||
// into a single local (such as a pointer, integer, bool, etc).
|
||||
const result: WValue = if (isByRef(ty, pt, func.target.*))
|
||||
switch (try func.bin_file.lowerUav(pt, val.toIntern(), .none, func.src_loc)) {
|
||||
.mcv => |mcv| .{ .memory = mcv.load_symbol },
|
||||
.fail => |err_msg| {
|
||||
func.err_msg = err_msg;
|
||||
return error.CodegenFail;
|
||||
},
|
||||
}
|
||||
.{ .memory = val.toIntern() }
|
||||
else
|
||||
try func.lowerConstant(val, ty);
|
||||
|
||||
@ -3164,20 +3155,14 @@ fn lowerUavRef(
|
||||
return .{ .imm32 = 0xaaaaaaaa };
|
||||
}
|
||||
|
||||
const decl_align = zcu.intern_pool.indexToKey(uav.orig_ty).ptr_type.flags.alignment;
|
||||
const res = try func.bin_file.lowerUav(pt, uav.val, decl_align, func.src_loc);
|
||||
const target_sym_index = switch (res) {
|
||||
.mcv => |mcv| mcv.load_symbol,
|
||||
.fail => |err_msg| {
|
||||
func.err_msg = err_msg;
|
||||
return error.CodegenFail;
|
||||
},
|
||||
};
|
||||
if (is_fn_body) {
|
||||
return .{ .function_index = target_sym_index };
|
||||
} else if (offset == 0) {
|
||||
return .{ .memory = target_sym_index };
|
||||
} else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
|
||||
return if (is_fn_body) .{
|
||||
.function_index = uav.val,
|
||||
} else if (offset == 0) .{
|
||||
.memory = uav.val,
|
||||
} else .{ .memory_offset = .{
|
||||
.pointer = uav.val,
|
||||
.offset = offset,
|
||||
} };
|
||||
}
|
||||
|
||||
fn lowerNavRef(func: *CodeGen, nav_index: InternPool.Nav.Index, offset: u32) InnerError!WValue {
|
||||
@ -3309,13 +3294,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
|
||||
.f64 => |f64_val| return .{ .float64 = f64_val },
|
||||
else => unreachable,
|
||||
},
|
||||
.slice => switch (try func.bin_file.lowerUav(pt, val.toIntern(), .none, func.src_loc)) {
|
||||
.mcv => |mcv| return .{ .memory = mcv.load_symbol },
|
||||
.fail => |err_msg| {
|
||||
func.err_msg = err_msg;
|
||||
return error.CodegenFail;
|
||||
},
|
||||
},
|
||||
.slice => return .{ .memory = val.toIntern() },
|
||||
.ptr => return func.lowerPtr(val.toIntern(), 0),
|
||||
.opt => if (ty.optionalReprIsPayload(zcu)) {
|
||||
const pl_ty = ty.optionalChild(zcu);
|
||||
|
@ -1348,18 +1348,14 @@ pub fn flush(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st
|
||||
return wasm.flushModule(arena, tid, prog_node);
|
||||
}
|
||||
|
||||
pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) anyerror!void {
|
||||
pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const sub_prog_node = prog_node.start("Wasm Prelink", 0);
|
||||
defer sub_prog_node.end();
|
||||
|
||||
if (wasm.object_init_funcs.items.len > 0) {
|
||||
// Zig has no constructors so these are only for object file inputs.
|
||||
mem.sortUnstable(InitFunc, wasm.object_init_funcs.items, {}, InitFunc.lessThan);
|
||||
try wasm.initializeCallCtorsFunction();
|
||||
}
|
||||
_ = wasm;
|
||||
}
|
||||
|
||||
pub fn flushModule(
|
||||
@ -1379,7 +1375,7 @@ pub fn flushModule(
|
||||
if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items);
|
||||
|
||||
if (wasm.base.zcu_object_sub_path) |path| {
|
||||
const module_obj_path = .{
|
||||
const module_obj_path: Path = .{
|
||||
.root_dir = wasm.base.emit.root_dir,
|
||||
.sub_path = if (fs.path.dirname(wasm.base.emit.sub_path)) |dirname|
|
||||
try fs.path.join(arena, &.{ dirname, path })
|
||||
|
@ -173,6 +173,14 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id) a
|
||||
}
|
||||
if (diags.hasErrors()) return error.LinkFailure;
|
||||
|
||||
// TODO only include init functions for objects with must_link=true or
|
||||
// which have any alive functions inside them.
|
||||
if (wasm.object_init_funcs.items.len > 0) {
|
||||
// Zig has no constructors so these are only for object file inputs.
|
||||
mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan);
|
||||
try f.functions.put(gpa, .__wasm_call_ctors, {});
|
||||
}
|
||||
|
||||
var any_passive_inits = false;
|
||||
|
||||
// Merge and order the data segments. Depends on garbage collection so that
|
||||
|
Loading…
Reference in New Issue
Block a user