Skip to content

Commit

Permalink
Merge #618
Browse files Browse the repository at this point in the history
618: Implement InternalEvent::Breakpoint in the llvm backend. r=nlewycky a=nlewycky

Enable now-working metering unit tests when run with the llvm backend.

Co-authored-by: Nick Lewycky <[email protected]>
Co-authored-by: nlewycky <[email protected]>
  • Loading branch information
bors[bot] and nlewycky committed Aug 1, 2019
2 parents a9e3eba + bebc3ee commit 1138a04
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 7 deletions.
32 changes: 29 additions & 3 deletions lib/llvm-backend/cpp/object_loader.hh
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#include <cstddef>
#include <cstdint>
#include <llvm/ExecutionEngine/RuntimeDyld.h>
#include <exception>
#include <iostream>
#include <sstream>
#include <exception>

#include <llvm/ExecutionEngine/RuntimeDyld.h>

typedef enum
{
Expand Down Expand Up @@ -77,6 +78,19 @@ struct UserException : UncatchableException
box_any_t error_data;
};

struct BreakpointException : UncatchableException
{
public:
BreakpointException(uintptr_t callback) : callback(callback) {}

virtual std::string description() const noexcept override
{
return "breakpoint exception";
}

uintptr_t callback;
};

struct WasmTrap : UncatchableException
{
public:
Expand Down Expand Up @@ -166,6 +180,8 @@ struct WasmModule

extern "C"
{
void callback_trampoline(void *, void *);

result_t module_load(const uint8_t *mem_ptr, size_t mem_size, callbacks_t callbacks, WasmModule **module_out)
{
*module_out = new WasmModule(mem_ptr, mem_size, callbacks);
Expand All @@ -192,6 +208,12 @@ extern "C"
throw UserException(data, vtable);
}

// Throw a pointer that's assumed to be codegen::BreakpointHandler on the
// rust side.
[[noreturn]] void throw_breakpoint(uintptr_t callback) {
throw BreakpointException(callback);
}

bool invoke_trampoline(
trampoline_t trampoline,
void *ctx,
Expand All @@ -217,6 +239,10 @@ extern "C"
*user_error = e.error_data;
return false;
}
catch (const BreakpointException &e) {
callback_trampoline(user_error, (void *)e.callback);
return false;
}
catch (const WasmException &e)
{
*trap_out = WasmTrap::Type::Unknown;
Expand All @@ -233,4 +259,4 @@ extern "C"
{
return module->get_func(llvm::StringRef(name));
}
}
}
4 changes: 3 additions & 1 deletion lib/llvm-backend/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ extern "C" {
fn module_delete(module: *mut LLVMModule);
fn get_func_symbol(module: *mut LLVMModule, name: *const c_char) -> *const vm::Func;

fn throw_trap(ty: i32);
fn throw_trap(ty: i32) -> !;
fn throw_breakpoint(ty: i64) -> !;

/// This should be the same as spliting up the fat pointer into two arguments,
/// but this is cleaner, I think?
Expand Down Expand Up @@ -103,6 +104,7 @@ fn get_callbacks() -> Callbacks {
fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _,

fn_name!("vm.exception.trap") => throw_trap as _,
fn_name!("vm.breakpoint") => throw_breakpoint as _,

_ => ptr::null(),
}
Expand Down
24 changes: 23 additions & 1 deletion lib/llvm-backend/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,21 @@ pub struct CodegenError {
pub message: String,
}

// This is only called by C++ code, the 'pub' + '#[no_mangle]' combination
// prevents unused function elimination.
#[no_mangle]
pub unsafe extern "C" fn callback_trampoline(
b: *mut Option<Box<dyn std::any::Any>>,
callback: *mut BreakpointHandler,
) {
let callback = Box::from_raw(callback);
let result: Result<(), Box<dyn std::any::Any>> = callback(BreakpointInfo { fault: None });
match result {
Ok(()) => *b = None,
Err(e) => *b = Some(e),
}
}

pub struct LLVMModuleCodeGenerator {
context: Option<Context>,
builder: Option<Builder>,
Expand Down Expand Up @@ -612,7 +627,14 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {
return Ok(());
}
InternalEvent::Breakpoint(_callback) => {
InternalEvent::Breakpoint(callback) => {
let raw = Box::into_raw(Box::new(callback)) as u64;
let callback = intrinsics.i64_ty.const_int(raw, false);
builder.build_call(
intrinsics.throw_breakpoint,
&[callback.as_basic_value_enum()],
"",
);
return Ok(());
}
InternalEvent::GetInternal(idx) => {
Expand Down
7 changes: 6 additions & 1 deletion lib/llvm-backend/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pub struct Intrinsics {
pub memory_size_shared_import: FunctionValue,

pub throw_trap: FunctionValue,
pub throw_breakpoint: FunctionValue,

pub ctx_ptr_ty: PointerType,
}
Expand Down Expand Up @@ -309,7 +310,6 @@ impl Intrinsics {
i32_ty.fn_type(&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic], false);

let ret_i1_take_i1_i1 = i1_ty.fn_type(&[i1_ty_basic, i1_ty_basic], false);

Self {
ctlz_i32: module.add_function("llvm.ctlz.i32", ret_i32_take_i32_i1, None),
ctlz_i64: module.add_function("llvm.ctlz.i64", ret_i64_take_i64_i1, None),
Expand Down Expand Up @@ -525,6 +525,11 @@ impl Intrinsics {
void_ty.fn_type(&[i32_ty_basic], false),
None,
),
throw_breakpoint: module.add_function(
"vm.breakpoint",
void_ty.fn_type(&[i64_ty_basic], false),
None,
),
ctx_ptr_ty,
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/middleware-common/src/metering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pub fn set_points_used_ctx(ctx: &mut Ctx, value: u64) {
ctx.set_internal(&INTERNAL_FIELD, value);
}

#[cfg(all(test, feature = "singlepass"))]
#[cfg(all(test, any(feature = "singlepass", feature = "llvm")))]
mod tests {
use super::*;
use wabt::wat2wasm;
Expand Down

0 comments on commit 1138a04

Please sign in to comment.