[wasm] Make FuncEnvironment functions fallible (fixes #752);
This commit is contained in:
@@ -71,7 +71,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
* `get_global` and `set_global` are handled by the environment.
|
||||
***********************************************************************************/
|
||||
Operator::GetGlobal { global_index } => {
|
||||
let val = match state.get_global(builder.func, global_index, environ) {
|
||||
let val = match state.get_global(builder.func, global_index, environ)? {
|
||||
GlobalVariable::Const(val) => val,
|
||||
GlobalVariable::Memory { gv, offset, ty } => {
|
||||
let addr = builder.ins().global_value(environ.pointer_type(), gv);
|
||||
@@ -82,7 +82,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
state.push1(val);
|
||||
}
|
||||
Operator::SetGlobal { global_index } => {
|
||||
match state.get_global(builder.func, global_index, environ) {
|
||||
match state.get_global(builder.func, global_index, environ)? {
|
||||
GlobalVariable::Const(_) => panic!("global #{} is a constant", global_index),
|
||||
GlobalVariable::Memory { gv, offset, ty } => {
|
||||
let addr = builder.ins().global_value(environ.pointer_type(), gv);
|
||||
@@ -137,7 +137,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
builder.ins().jump(loop_body, &[]);
|
||||
state.push_loop(loop_body, next, num_return_values(ty));
|
||||
builder.switch_to_block(loop_body);
|
||||
environ.translate_loop_header(builder.cursor());
|
||||
environ.translate_loop_header(builder.cursor())?;
|
||||
}
|
||||
Operator::If { ty } => {
|
||||
let val = state.pop1();
|
||||
@@ -348,7 +348,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
* argument referring to an index in the external functions table of the module.
|
||||
************************************************************************************/
|
||||
Operator::Call { function_index } => {
|
||||
let (fref, num_args) = state.get_direct_func(builder.func, function_index, environ);
|
||||
let (fref, num_args) = state.get_direct_func(builder.func, function_index, environ)?;
|
||||
let call = environ.translate_call(
|
||||
builder.cursor(),
|
||||
FuncIndex::from_u32(function_index),
|
||||
@@ -369,8 +369,8 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
Operator::CallIndirect { index, table_index } => {
|
||||
// `index` is the index of the function's signature and `table_index` is the index of
|
||||
// the table to search the function in.
|
||||
let (sigref, num_args) = state.get_indirect_sig(builder.func, index, environ);
|
||||
let table = state.get_table(builder.func, table_index, environ);
|
||||
let (sigref, num_args) = state.get_indirect_sig(builder.func, index, environ)?;
|
||||
let table = state.get_table(builder.func, table_index, environ)?;
|
||||
let callee = state.pop1();
|
||||
let call = environ.translate_call_indirect(
|
||||
builder.cursor(),
|
||||
@@ -398,13 +398,13 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
// The WebAssembly MVP only supports one linear memory, but we expect the reserved
|
||||
// argument to be a memory index.
|
||||
let heap_index = MemoryIndex::from_u32(reserved);
|
||||
let heap = state.get_heap(builder.func, reserved, environ);
|
||||
let heap = state.get_heap(builder.func, reserved, environ)?;
|
||||
let val = state.pop1();
|
||||
state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?)
|
||||
}
|
||||
Operator::MemorySize { reserved } => {
|
||||
let heap_index = MemoryIndex::from_u32(reserved);
|
||||
let heap = state.get_heap(builder.func, reserved, environ);
|
||||
let heap = state.get_heap(builder.func, reserved, environ)?;
|
||||
state.push1(environ.translate_memory_size(builder.cursor(), heap_index, heap)?);
|
||||
}
|
||||
/******************************* Load instructions ***********************************
|
||||
@@ -414,72 +414,72 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
Operator::I32Load8U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Uload8, I32, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Uload8, I32, builder, state, environ)?;
|
||||
}
|
||||
Operator::I32Load16U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Uload16, I32, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Uload16, I32, builder, state, environ)?;
|
||||
}
|
||||
Operator::I32Load8S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Sload8, I32, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Sload8, I32, builder, state, environ)?;
|
||||
}
|
||||
Operator::I32Load16S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Sload16, I32, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Sload16, I32, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load8U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Uload8, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Uload8, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load16U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Uload16, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Uload16, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load8S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Sload8, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Sload8, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load16S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Sload16, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Sload16, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load32S {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Sload32, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Sload32, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load32U {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Uload32, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Uload32, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::I32Load {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Load, I32, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Load, I32, builder, state, environ)?;
|
||||
}
|
||||
Operator::F32Load {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Load, F32, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Load, F32, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Load {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Load, I64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Load, I64, builder, state, environ)?;
|
||||
}
|
||||
Operator::F64Load {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_load(offset, ir::Opcode::Load, F64, builder, state, environ);
|
||||
translate_load(offset, ir::Opcode::Load, F64, builder, state, environ)?;
|
||||
}
|
||||
/****************************** Store instructions ***********************************
|
||||
* Wasm specifies an integer alignment flag but we drop it in Cranelift.
|
||||
@@ -497,7 +497,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::F64Store {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_store(offset, ir::Opcode::Store, builder, state, environ);
|
||||
translate_store(offset, ir::Opcode::Store, builder, state, environ)?;
|
||||
}
|
||||
Operator::I32Store8 {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
@@ -505,7 +505,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::I64Store8 {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_store(offset, ir::Opcode::Istore8, builder, state, environ);
|
||||
translate_store(offset, ir::Opcode::Istore8, builder, state, environ)?;
|
||||
}
|
||||
Operator::I32Store16 {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
@@ -513,12 +513,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::I64Store16 {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_store(offset, ir::Opcode::Istore16, builder, state, environ);
|
||||
translate_store(offset, ir::Opcode::Istore16, builder, state, environ)?;
|
||||
}
|
||||
Operator::I64Store32 {
|
||||
memarg: MemoryImmediate { flags: _, offset },
|
||||
} => {
|
||||
translate_store(offset, ir::Opcode::Istore32, builder, state, environ);
|
||||
translate_store(offset, ir::Opcode::Istore32, builder, state, environ)?;
|
||||
}
|
||||
/****************************** Nullary Operators ************************************/
|
||||
Operator::I32Const { value } => state.push1(builder.ins().iconst(I32, i64::from(value))),
|
||||
@@ -1175,10 +1175,10 @@ fn translate_load<FE: FuncEnvironment + ?Sized>(
|
||||
builder: &mut FunctionBuilder,
|
||||
state: &mut TranslationState,
|
||||
environ: &mut FE,
|
||||
) {
|
||||
) -> WasmResult<()> {
|
||||
let addr32 = state.pop1();
|
||||
// We don't yet support multiple linear memories.
|
||||
let heap = state.get_heap(builder.func, 0, environ);
|
||||
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||
let (base, offset) = get_heap_addr(heap, addr32, offset, environ.pointer_type(), builder);
|
||||
// Note that we don't set `is_aligned` here, even if the load instruction's
|
||||
// alignment immediate says it's aligned, because WebAssembly's immediate
|
||||
@@ -1188,6 +1188,7 @@ fn translate_load<FE: FuncEnvironment + ?Sized>(
|
||||
.ins()
|
||||
.Load(opcode, result_ty, flags, offset.into(), base);
|
||||
state.push1(dfg.first_result(load));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Translate a store instruction.
|
||||
@@ -1197,18 +1198,19 @@ fn translate_store<FE: FuncEnvironment + ?Sized>(
|
||||
builder: &mut FunctionBuilder,
|
||||
state: &mut TranslationState,
|
||||
environ: &mut FE,
|
||||
) {
|
||||
) -> WasmResult<()> {
|
||||
let (addr32, val) = state.pop2();
|
||||
let val_ty = builder.func.dfg.value_type(val);
|
||||
|
||||
// We don't yet support multiple linear memories.
|
||||
let heap = state.get_heap(builder.func, 0, environ);
|
||||
let heap = state.get_heap(builder.func, 0, environ)?;
|
||||
let (base, offset) = get_heap_addr(heap, addr32, offset, environ.pointer_type(), builder);
|
||||
// See the comments in `translate_load` about the flags.
|
||||
let flags = MemFlags::new();
|
||||
builder
|
||||
.ins()
|
||||
.Store(opcode, val_ty, flags, offset.into(), val, base);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut TranslationState) {
|
||||
|
||||
Reference in New Issue
Block a user