mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 08:14:48 +00:00
Add tests and move tests to wasm's own file
This commit is contained in:
parent
4b2538f72c
commit
6c19aeddca
@ -48,7 +48,7 @@ pub const Context = struct {
|
||||
/// Table to save `WValue`'s generated by an `Inst`
|
||||
values: ValueTable,
|
||||
/// `bytes` contains the wasm bytecode belonging to the 'code' section.
|
||||
bytes: ArrayList(u8),
|
||||
code: ArrayList(u8),
|
||||
/// Contains the generated function type bytecode for the current function
|
||||
/// found in `decl`
|
||||
func_type_data: ArrayList(u8),
|
||||
@ -56,8 +56,7 @@ pub const Context = struct {
|
||||
/// NOTE: arguments share the index with locals therefore the first variable
|
||||
/// will have the index that comes after the last argument's index
|
||||
local_index: u32 = 0,
|
||||
/// If codegen fails, an error messages will be allocated and saved
|
||||
/// in `err_msg`
|
||||
/// If codegen fails, an error messages will be allocated and saved in `err_msg`
|
||||
err_msg: *Compilation.ErrorMsg,
|
||||
|
||||
const InnerError = error{
|
||||
@ -74,6 +73,8 @@ pub const Context = struct {
|
||||
/// Resolves the `WValue` for the given instruction `inst`
|
||||
/// When the given instruction has a `Value`, it returns a constant instead
|
||||
fn resolveInst(self: Context, inst: *Inst) WValue {
|
||||
if (!inst.ty.hasCodeGenBits()) return .none;
|
||||
|
||||
if (inst.value()) |_| {
|
||||
return WValue{ .constant = inst };
|
||||
}
|
||||
@ -83,7 +84,7 @@ pub const Context = struct {
|
||||
|
||||
/// Writes the bytecode depending on the given `WValue` in `val`
|
||||
fn emitWValue(self: *Context, val: WValue) InnerError!void {
|
||||
const writer = self.bytes.writer();
|
||||
const writer = self.code.writer();
|
||||
switch (val) {
|
||||
.none, .block_idx => {},
|
||||
.local => |idx| {
|
||||
@ -127,14 +128,14 @@ pub const Context = struct {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the wasm bytecode for the given `code`
|
||||
/// Generates the wasm bytecode for the function declaration belonging to `Context`
|
||||
pub fn gen(self: *Context) InnerError!void {
|
||||
assert(self.bytes.items.len == 0);
|
||||
assert(self.code.items.len == 0);
|
||||
try self.genFunctype();
|
||||
const writer = self.bytes.writer();
|
||||
const writer = self.code.writer();
|
||||
|
||||
// Reserve space to write the size after generating the code
|
||||
try self.bytes.resize(5);
|
||||
try self.code.resize(5);
|
||||
|
||||
// Write instructions
|
||||
// TODO: check for and handle death of instructions
|
||||
@ -170,8 +171,8 @@ pub const Context = struct {
|
||||
|
||||
// Fill in the size of the generated code to the reserved space at the
|
||||
// beginning of the buffer.
|
||||
const size = self.bytes.items.len - 5 + self.decl.fn_link.wasm.?.idx_refs.items.len * 5;
|
||||
leb.writeUnsignedFixed(5, self.bytes.items[0..5], @intCast(u32, size));
|
||||
const size = self.code.items.len - 5 + self.decl.fn_link.wasm.?.idx_refs.items.len * 5;
|
||||
leb.writeUnsignedFixed(5, self.code.items[0..5], @intCast(u32, size));
|
||||
}
|
||||
|
||||
fn genInst(self: *Context, inst: *Inst) InnerError!WValue {
|
||||
@ -198,6 +199,7 @@ pub const Context = struct {
|
||||
}
|
||||
|
||||
fn genRet(self: *Context, inst: *Inst.UnOp) InnerError!WValue {
|
||||
// TODO: Implement tail calls
|
||||
const operand = self.resolveInst(inst.operand);
|
||||
try self.emitWValue(operand);
|
||||
return WValue.none;
|
||||
@ -214,12 +216,12 @@ pub const Context = struct {
|
||||
try self.emitWValue(arg_val);
|
||||
}
|
||||
|
||||
try self.bytes.append(0x10); // call
|
||||
try self.code.append(0x10); // call
|
||||
|
||||
// The function index immediate argument will be filled in using this data
|
||||
// in link.Wasm.flush().
|
||||
try self.decl.fn_link.wasm.?.idx_refs.append(self.gpa, .{
|
||||
.offset = @intCast(u32, self.bytes.items.len),
|
||||
.offset = @intCast(u32, self.code.items.len),
|
||||
.decl = target,
|
||||
});
|
||||
|
||||
@ -232,7 +234,7 @@ pub const Context = struct {
|
||||
}
|
||||
|
||||
fn genStore(self: *Context, inst: *Inst.BinOp) InnerError!WValue {
|
||||
const writer = self.bytes.writer();
|
||||
const writer = self.code.writer();
|
||||
|
||||
const lhs = self.resolveInst(inst.lhs);
|
||||
const rhs = self.resolveInst(inst.rhs);
|
||||
@ -262,12 +264,12 @@ pub const Context = struct {
|
||||
try self.emitWValue(lhs);
|
||||
try self.emitWValue(rhs);
|
||||
|
||||
try self.bytes.append(0x6A); // i32.add
|
||||
try self.code.append(0x6A); // i32.add
|
||||
return WValue.none;
|
||||
}
|
||||
|
||||
fn emitConstant(self: *Context, inst: *Inst.Constant) InnerError!void {
|
||||
const writer = self.bytes.writer();
|
||||
const writer = self.code.writer();
|
||||
switch (inst.base.ty.tag()) {
|
||||
.u32 => {
|
||||
try writer.writeByte(0x41); // i32.const
|
||||
|
||||
@ -122,7 +122,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
|
||||
var context = codegen.Context{
|
||||
.gpa = self.base.allocator,
|
||||
.values = codegen.ValueTable.init(self.base.allocator),
|
||||
.bytes = managed_code,
|
||||
.code = managed_code,
|
||||
.func_type_data = managed_functype,
|
||||
.decl = decl,
|
||||
.err_msg = undefined,
|
||||
@ -140,7 +140,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
|
||||
};
|
||||
|
||||
fn_data.functype = context.func_type_data.toUnmanaged();
|
||||
fn_data.code = context.bytes.toUnmanaged();
|
||||
fn_data.code = context.code.toUnmanaged();
|
||||
}
|
||||
|
||||
pub fn updateDeclExports(
|
||||
|
||||
@ -21,17 +21,13 @@ const linux_riscv64 = std.zig.CrossTarget{
|
||||
.os_tag = .linux,
|
||||
};
|
||||
|
||||
const wasi = std.zig.CrossTarget{
|
||||
.cpu_arch = .wasm32,
|
||||
.os_tag = .wasi,
|
||||
};
|
||||
|
||||
pub fn addCases(ctx: *TestContext) !void {
|
||||
try @import("cbe.zig").addCases(ctx);
|
||||
try @import("spu-ii.zig").addCases(ctx);
|
||||
try @import("arm.zig").addCases(ctx);
|
||||
try @import("aarch64.zig").addCases(ctx);
|
||||
try @import("llvm.zig").addCases(ctx);
|
||||
try @import("wasm.zig").addCases(ctx);
|
||||
|
||||
{
|
||||
var case = ctx.exe("hello world with updates", linux_x64);
|
||||
@ -1158,62 +1154,6 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
var case = ctx.exe("wasm function calls", wasi);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ foo();
|
||||
\\ bar();
|
||||
\\ return 42;
|
||||
\\}
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\ bar();
|
||||
\\}
|
||||
\\fn bar() void {}
|
||||
,
|
||||
"42\n",
|
||||
);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() i64 {
|
||||
\\ bar();
|
||||
\\ foo();
|
||||
\\ foo();
|
||||
\\ bar();
|
||||
\\ foo();
|
||||
\\ bar();
|
||||
\\ return 42;
|
||||
\\}
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\}
|
||||
\\fn bar() void {}
|
||||
,
|
||||
"42\n",
|
||||
);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() f32 {
|
||||
\\ bar();
|
||||
\\ foo();
|
||||
\\ return 42.0;
|
||||
\\}
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\ bar();
|
||||
\\ bar();
|
||||
\\}
|
||||
\\fn bar() void {}
|
||||
,
|
||||
// This is what you get when you take the bits of the IEE-754
|
||||
// representation of 42.0 and reinterpret them as an unsigned
|
||||
// integer. Guess that's a bug in wasmtime.
|
||||
"1109917696\n",
|
||||
);
|
||||
}
|
||||
|
||||
ctx.compileError("function redefinition", linux_x64,
|
||||
\\fn entry() void {}
|
||||
\\fn entry() void {}
|
||||
|
||||
125
test/stage2/wasm.zig
Normal file
125
test/stage2/wasm.zig
Normal file
@ -0,0 +1,125 @@
|
||||
const std = @import("std");
|
||||
const TestContext = @import("../../src/test.zig").TestContext;
|
||||
|
||||
const wasi = std.zig.CrossTarget{
|
||||
.cpu_arch = .wasm32,
|
||||
.os_tag = .wasi,
|
||||
};
|
||||
|
||||
pub fn addCases(ctx: *TestContext) !void {
|
||||
{
|
||||
var case = ctx.exe("wasm function calls", wasi);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ foo();
|
||||
\\ bar();
|
||||
\\ return 42;
|
||||
\\}
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\ bar();
|
||||
\\}
|
||||
\\fn bar() void {}
|
||||
,
|
||||
"42\n",
|
||||
);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() i64 {
|
||||
\\ bar();
|
||||
\\ foo();
|
||||
\\ foo();
|
||||
\\ bar();
|
||||
\\ foo();
|
||||
\\ bar();
|
||||
\\ return 42;
|
||||
\\}
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\}
|
||||
\\fn bar() void {}
|
||||
,
|
||||
"42\n",
|
||||
);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() f32 {
|
||||
\\ bar();
|
||||
\\ foo();
|
||||
\\ return 42.0;
|
||||
\\}
|
||||
\\fn foo() void {
|
||||
\\ bar();
|
||||
\\ bar();
|
||||
\\ bar();
|
||||
\\}
|
||||
\\fn bar() void {}
|
||||
,
|
||||
// This is what you get when you take the bits of the IEE-754
|
||||
// representation of 42.0 and reinterpret them as an unsigned
|
||||
// integer. Guess that's a bug in wasmtime.
|
||||
"1109917696\n",
|
||||
);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ foo(10, 20);
|
||||
\\ return 5;
|
||||
\\}
|
||||
\\fn foo(x: u32, y: u32) void {}
|
||||
, "5\n");
|
||||
}
|
||||
|
||||
{
|
||||
var case = ctx.exe("wasm locals", wasi);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ var i: u32 = 5;
|
||||
\\ var y: f32 = 42.0;
|
||||
\\ var x: u32 = 10;
|
||||
\\ return i;
|
||||
\\}
|
||||
, "5\n");
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ var i: u32 = 5;
|
||||
\\ var y: f32 = 42.0;
|
||||
\\ var x: u32 = 10;
|
||||
\\ foo(i, x);
|
||||
\\ i = x;
|
||||
\\ return i;
|
||||
\\}
|
||||
\\fn foo(x: u32, y: u32) void {
|
||||
\\ var i: u32 = 10;
|
||||
\\ i = x;
|
||||
\\}
|
||||
, "10\n");
|
||||
}
|
||||
|
||||
{
|
||||
var case = ctx.exe("wasm binary operands", wasi);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ var i: u32 = 5;
|
||||
\\ i += 20;
|
||||
\\ return i;
|
||||
\\}
|
||||
, "25\n");
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() u32 {
|
||||
\\ var i: u32 = 5;
|
||||
\\ i += 20;
|
||||
\\ var result: u32 = foo(i, 10);
|
||||
\\ return result;
|
||||
\\}
|
||||
\\fn foo(x: u32, y: u32) u32 {
|
||||
\\ return x + y;
|
||||
\\}
|
||||
, "35\n");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user