-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call spec #45
Call spec #45
Changes from 3 commits
5681b7c
d9f1a2c
038a2a0
247d5b5
e694b9d
12db29f
62594f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ public Machine(Instance instance) { | |
this.callStack = new Stack<>(); | ||
} | ||
|
||
public Value call(int funcId, Value[] args, boolean popResults) throws ChicoryException { | ||
public Value[] call(int funcId, Value[] args, boolean popResults) throws ChicoryException { | ||
var func = instance.getFunction(funcId); | ||
if (func != null) { | ||
this.callStack.push(new StackFrame(funcId, 0, args, func.getLocals())); | ||
|
@@ -46,13 +46,20 @@ public Value call(int funcId, Value[] args, boolean popResults) throws ChicoryEx | |
var type = instance.getTypes()[typeId]; | ||
if (type.getReturns().length == 0) return null; | ||
if (this.stack.size() == 0) return null; | ||
return this.stack.pop(); | ||
|
||
var totalResults = type.getReturns().length; | ||
var results = new Value[totalResults]; | ||
for (var i = totalResults - 1; i >= 0; i--) { | ||
results[i] = this.stack.pop(); | ||
} | ||
return results; | ||
} | ||
|
||
void eval(List<Instruction> code) throws ChicoryException { | ||
try { | ||
var frame = callStack.peek(); | ||
boolean shouldReturn = false; | ||
|
||
loop: | ||
while (frame.pc < code.size()) { | ||
if (shouldReturn) return; | ||
|
@@ -123,27 +130,19 @@ void eval(List<Instruction> code) throws ChicoryException { | |
case RETURN: | ||
shouldReturn = true; | ||
break; | ||
// case CALL_INDIRECT: | ||
// { | ||
// // var index = | ||
// this.stack.pop().asInt(); | ||
// // var funcId = | ||
// // instance.getTable().getFuncRef(index); | ||
// // var typeId = | ||
// // instance.getFunctionTypes().get(funcId); | ||
// // var type = | ||
// instance.getTypes().get(typeId); | ||
// // // given a list of param | ||
// types, let's pop those | ||
// // params off the stack | ||
// // // and pass as args to | ||
// the function call | ||
// // var args = | ||
// // extractArgsForParams(type.paramTypes()); | ||
// // call(funcId, args, | ||
// false); | ||
// break; | ||
// } | ||
case CALL_INDIRECT: | ||
{ | ||
var index = this.stack.pop().asInt(); | ||
var funcId = instance.getTable().getFuncRef(index); | ||
var typeId = instance.getFunctionTypes()[funcId]; | ||
var type = instance.getTypes()[typeId]; | ||
// given a list of param types, let's pop those params off the stack | ||
// and pass as args to the function call | ||
var args = extractArgsForParams(type.getParams()); | ||
call(funcId, args, false); | ||
frame.pc = instruction.getAddress(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the intention of this? So, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay discussed offline. removing it for the time being then i will investigate. |
||
break; | ||
} | ||
case DROP: | ||
this.stack.pop(); | ||
break; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -137,6 +137,24 @@ public Instance instantiate(HostFunction[] hostFunctions) { | |
exports.put("_start", export); | ||
} | ||
|
||
Table table = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is a little bit naive on my part but I think it works for the time being. We can update it when we get to the other specs that address tables and elements. |
||
if (module.getTableSection() != null) { | ||
if (module.getTableSection().getTables().length > 1) { | ||
throw new ChicoryException("We don't currently support more than 1 table"); | ||
} | ||
table = module.getTableSection().getTables()[0]; | ||
if (module.getElementSection() != null) { | ||
for (var el : module.getElementSection().getElements()) { | ||
var idx = el.getTableIndex(); | ||
if (idx != 0) | ||
throw new ChicoryException("We don't currently support more than 1 table"); | ||
for (var fi : el.getFuncIndices()) { | ||
table.addFuncRef((int) fi); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return new Instance( | ||
this, | ||
globalInitializers, | ||
|
@@ -145,7 +163,8 @@ public Instance instantiate(HostFunction[] hostFunctions) { | |
functions, | ||
types, | ||
functionTypes, | ||
hostFuncs); | ||
hostFuncs, | ||
table); | ||
} | ||
|
||
private HostFunction[] mapHostFunctions(Import[] imports, HostFunction[] hostFunctions) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,27 +41,27 @@ public void shouldWorkFactorial() { | |
var module = Module.build("src/test/resources/wasm/iterfact.wat.wasm"); | ||
var instance = module.instantiate(); | ||
var iterFact = instance.getExport("iterFact"); | ||
var result = iterFact.apply(Value.i32(5)); | ||
var result = iterFact.apply(Value.i32(5))[0]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a big deal for now, but I wonder if it makes sense to have another method similar to get export, or maybe something on ExportFunction that can make this a little cleaner if you know it only has 1 return. |
||
assertEquals(120, result.asInt()); | ||
} | ||
|
||
@Test | ||
public void shouldSupportBrTable() { | ||
var instance = Module.build("src/test/resources/wasm/br_table.wat.wasm").instantiate(); | ||
var switchLike = instance.getExport("switch_like"); | ||
var result = switchLike.apply(Value.i32(0)); | ||
var result = switchLike.apply(Value.i32(0))[0]; | ||
assertEquals(102, result.asInt()); | ||
result = switchLike.apply(Value.i32(1)); | ||
result = switchLike.apply(Value.i32(1))[0]; | ||
assertEquals(101, result.asInt()); | ||
result = switchLike.apply(Value.i32(2)); | ||
result = switchLike.apply(Value.i32(2))[0]; | ||
assertEquals(100, result.asInt()); | ||
result = switchLike.apply(Value.i32(-1)); | ||
result = switchLike.apply(Value.i32(-1))[0]; | ||
assertEquals(103, result.asInt()); | ||
result = switchLike.apply(Value.i32(3)); | ||
result = switchLike.apply(Value.i32(3))[0]; | ||
assertEquals(103, result.asInt()); | ||
result = switchLike.apply(Value.i32(4)); | ||
result = switchLike.apply(Value.i32(4))[0]; | ||
assertEquals(103, result.asInt()); | ||
result = switchLike.apply(Value.i32(100)); | ||
result = switchLike.apply(Value.i32(100))[0]; | ||
assertEquals(103, result.asInt()); | ||
} | ||
|
||
|
@@ -70,14 +70,14 @@ public void shouldExerciseBranches() { | |
var module = Module.build("src/test/resources/wasm/branching.wat.wasm").instantiate(); | ||
var foo = module.getExport("foo"); | ||
|
||
var result = foo.apply(Value.i32(0)); | ||
var result = foo.apply(Value.i32(0))[0]; | ||
assertEquals(42, result.asInt()); | ||
|
||
result = foo.apply(Value.i32(1)); | ||
result = foo.apply(Value.i32(1))[0]; | ||
assertEquals(99, result.asInt()); | ||
|
||
for (var i = 2; i < 100; i++) { | ||
result = foo.apply(Value.i32(i)); | ||
result = foo.apply(Value.i32(i))[0]; | ||
assertEquals(7, result.asInt()); | ||
} | ||
} | ||
|
@@ -113,7 +113,7 @@ public void shouldComputeFactorial() { | |
|
||
// don't make this too big we will overflow 32 bits | ||
for (var i = 0; i < 10; i++) { | ||
var result = iterFact.apply(Value.i32(i)); | ||
var result = iterFact.apply(Value.i32(i))[0]; | ||
// test against an oracle Java implementation | ||
assertEquals(factorial(i), result.asInt()); | ||
} | ||
|
@@ -159,7 +159,7 @@ public void shouldTrapOnUnreachable() { | |
public void shouldSupportGlobals() { | ||
var instance = Module.build("src/test/resources/wasm/globals.wat.wasm").instantiate(); | ||
var doit = instance.getExport("doit"); | ||
var result = doit.apply(Value.i32(32)); | ||
var result = doit.apply(Value.i32(32))[0]; | ||
assertEquals(42, result.asInt()); | ||
} | ||
|
||
|
@@ -180,7 +180,7 @@ public void shouldRunBasicCProgram() { | |
// check with: wasmtime src/test/resources/wasm/basic.c.wasm --invoke run | ||
var instance = Module.build("src/test/resources/wasm/basic.c.wasm").instantiate(); | ||
var run = instance.getExport("run"); | ||
var result = run.apply(); | ||
var result = run.apply()[0]; | ||
assertEquals(42, result.asInt()); | ||
} | ||
|
||
|
@@ -206,25 +206,26 @@ public void shouldRunBasicCProgram() { | |
public void shouldWorkWithMemoryOps() { | ||
var instance = Module.build("src/test/resources/wasm/memory.wat.wasm").instantiate(); | ||
var run = instance.getExport("run32"); | ||
var result = run.apply(Value.i32(42)); | ||
var results = run.apply(Value.i32(42)); | ||
var result = results[0]; | ||
assertEquals(42, result.asInt()); | ||
|
||
result = run.apply(Value.i32(Integer.MAX_VALUE)); | ||
result = run.apply(Value.i32(Integer.MAX_VALUE))[0]; | ||
assertEquals(Integer.MAX_VALUE, result.asInt()); | ||
|
||
result = run.apply(Value.i32(Integer.MIN_VALUE)); | ||
result = run.apply(Value.i32(Integer.MIN_VALUE))[0]; | ||
assertEquals(Integer.MIN_VALUE, result.asInt()); | ||
|
||
run = instance.getExport("run64"); | ||
result = run.apply(Value.i64(42)); | ||
result = run.apply(Value.i64(42))[0]; | ||
assertEquals(42L, result.asLong()); | ||
|
||
run = instance.getExport("run64"); | ||
result = run.apply(Value.i64(Long.MIN_VALUE)); | ||
result = run.apply(Value.i64(Long.MIN_VALUE))[0]; | ||
assertEquals(Long.MIN_VALUE, result.asLong()); | ||
|
||
run = instance.getExport("run64"); | ||
result = run.apply(Value.i64(Long.MAX_VALUE)); | ||
result = run.apply(Value.i64(Long.MAX_VALUE))[0]; | ||
assertEquals(Long.MAX_VALUE, result.asLong()); | ||
} | ||
|
||
|
@@ -233,7 +234,7 @@ public void shouldRunKitchenSink() { | |
// check with: wasmtime src/test/resources/wasm/kitchensink.wat.wasm --invoke run 100 | ||
var instance = Module.build("src/test/resources/wasm/kitchensink.wat.wasm").instantiate(); | ||
var run = instance.getExport("run"); | ||
assertEquals(6, run.apply(Value.i32(100)).asInt()); | ||
assertEquals(6, run.apply(Value.i32(100))[0].asInt()); | ||
} | ||
|
||
// @Test | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIce!