Skip to content

Commit

Permalink
Task/flesh out calls (#118)
Browse files Browse the repository at this point in the history
* implement ternary folding

* Add tests for call's provided globals

* clippy

* add more tests for prov-globals

* fmt

* Implement imms for calls

* Fix mem size in whamm when emitted strings
  • Loading branch information
ejrgilbert authored Jul 31, 2024
1 parent 0b40391 commit 87ece61
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 183 deletions.
12 changes: 12 additions & 0 deletions src/emitter/rewriting/module_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const UNEXPECTED_ERR_MSG: &str =
pub struct MemoryTracker {
pub mem_id: u32,
pub curr_mem_offset: usize,
pub required_initial_mem_size: u64,
pub emitted_strings: HashMap<String, StringAddr>,
}

Expand Down Expand Up @@ -298,6 +299,17 @@ impl<'a, 'b, 'c, 'd> ModuleEmitter<'a, 'b, 'c, 'd> {
}
}

pub(crate) fn memory_grow(&mut self) {
// If we've emitted any strings, bump the app's memory up to account for that
if !self.mem_tracker.emitted_strings.is_empty() {
if let Some(mem) = self.app_wasm.memories.get_mut(0) {
if mem.initial < self.mem_tracker.required_initial_mem_size {
mem.initial = self.mem_tracker.required_initial_mem_size;
}
}
}
}

pub(crate) fn emit_global_getter(
&mut self,
global_id: &u32,
Expand Down
7 changes: 7 additions & 0 deletions src/emitter/rewriting/rules/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,13 @@ impl Event for OpcodeEvent {
val: func_info.module.to_string(),
}),
);
loc_info.static_data.insert(
"imm0".to_string(),
Some(Value::Integer {
ty: DataType::I32,
val: *fid as i32,
}),
);

// add the probes for this event
loc_info.add_probes(self.probe_spec(), &self.probes);
Expand Down
5 changes: 4 additions & 1 deletion src/generator/init_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ impl InitGenerator<'_, '_, '_, '_, '_> {
// Reset the symbol table in the emitter just in case
self.emitter.reset_children();
// Generate globals and fns defined by `whamm` (this should modify the app_wasm)
self.visit_whamm(whamm)
let is_success = self.visit_whamm(whamm);
self.emitter.memory_grow(); // account for emitted strings in memory

is_success
}

// Private helper functions
Expand Down
37 changes: 35 additions & 2 deletions src/generator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,41 @@ impl ExprFolder {
None
}

fn fold_ternary(_ternary: &Expr, _table: &SymbolTable) -> Expr {
todo!()
fn fold_ternary(ternary: &Expr, table: &SymbolTable) -> Expr {
match ternary {
Expr::Ternary {
cond, conseq, alt, ..
} => {
let cond = ExprFolder::fold_expr(cond, table);
let conseq = ExprFolder::fold_expr(conseq, table);
let alt = ExprFolder::fold_expr(alt, table);

// check if the condition folds to true/false!
let cond_val = ExprFolder::get_single_bool(&cond);
return if let Some(cond_bool) = cond_val {
// the condition folds to a primitive bool!
if cond_bool {
// it's a true, evaluates to the conseq
conseq
} else {
// it's a false, evaluates to the alt
alt
}
} else {
// condition doesn't fold to a primitive, return folded variation.
Expr::Ternary {
cond: Box::new(cond),
conseq: Box::new(conseq),
alt: Box::new(alt),
loc: None,
}
};
}
_ => {
// ignore
}
}
ternary.clone()
}

fn fold_call(call: &Expr, _table: &SymbolTable) -> Expr {
Expand Down
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ fn run_instr(
panic!("only single memory is supported")
};
let mut mem_tracker = MemoryTracker {
mem_id: 0, // Assuming the ID of the first memory is 0!
mem_id: 0, // Assuming the ID of the first memory is 0!
curr_mem_offset: 1_052_576, // Set default memory base address to DEFAULT + 4KB = 1048576 bytes + 4000 bytes = 1052576 bytes
required_initial_mem_size: 27, // Size memory must be to account for the added data
emitted_strings: HashMap::new(),
};

Expand Down
3 changes: 2 additions & 1 deletion tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ pub fn run_whamm(app_wasm: &mut Module, whamm_script: &String, script_path: &str
panic!("only single memory is supported")
};
let mut mem_tracker = MemoryTracker {
mem_id: 0, // Assuming the ID of the first memory is 0!
mem_id: 0, // Assuming the ID of the first memory is 0!
curr_mem_offset: 1_052_576, // Set default memory base address to DEFAULT + 4KB = 1048576 bytes + 4000 bytes = 1052576 bytes
required_initial_mem_size: 27, // Size memory must be to account for the added data
emitted_strings: HashMap::new(),
};

Expand Down
59 changes: 59 additions & 0 deletions tests/wast_suite/events/wasm_opcodes/call/import/imms.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
;; Test `wasm:opcode:call` event

;; Auxiliary module to import from

(module
(func (export "dummy_five_params") (param i32 i32 i32 i32 i32) (result i32)
local.get 0
local.get 1
i32.add
local.get 2
i32.add
local.get 3
i32.add
local.get 4
i32.add
)
)

(register "test")

;; @instrument
(module
;; Imports
(type (;0;) (func (param i32 i32 i32 i32 i32) (result i32)))
(import "test" "dummy_five_params" (func $dummy_five_params (type 0)))

;; Globals
(global $var (mut i32) (i32.const 0))

;; Global getters
(func $get_global_var (result i32)
(global.get $var)
)

;; Test case functions
(func $five_params
(call $dummy_five_params (i32.const 0) (i32.const 1) (i32.const 2) (i32.const 3) (i32.const 4))
global.set $var
)

(start $five_params)
(export "five_params" (func $five_params))
(export "get_global_var" (func $get_global_var))
(memory (;0;) 1)
)

;; ---------------------------------
;; ==== IMMS, predicate, `imm0` ====
;; WHAMM --> i32 count; wasm:opcode:call:before / imm0 == 1 / { count++; }
(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'
;; WHAMM --> i32 count; wasm:opcode:call:before / imm0 == 0 / { count++; }
(assert_return (invoke "get_count") (i32.const 1)) ;; predicate is 'true'

;; ----------------------------
;; ==== IMMS, body, `imm0` ====
;; WHAMM --> i32 count; wasm:opcode:call:before { count = imm0 == 1 ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 0)) ;; condition is 'false'
;; WHAMM --> i32 count; wasm:opcode:call:before { count = imm0 == 0 ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 1)) ;; condition is 'true'
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
(start $five_params)
(export "five_params" (func $five_params))
(export "get_global_var" (func $get_global_var))
(memory (;0;) 27) ;; TODO -- Memory must have enough pages to account for the injected strings! Make this work via whamm!
(memory (;0;) 1)
)

;; -------------------------------------------------
Expand Down
87 changes: 87 additions & 0 deletions tests/wast_suite/events/wasm_opcodes/call/import/prov-globals.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
;; Test `wasm:opcode:call` event

;; Auxiliary module to import from

(module
(func (export "dummy_five_params") (param i32 i32 i32 i32 i32) (result i32)
local.get 0
local.get 1
i32.add
local.get 2
i32.add
local.get 3
i32.add
local.get 4
i32.add
)
)

(register "test")

;; @instrument
(module
;; Imports
(type (;0;) (func (param i32 i32 i32 i32 i32) (result i32)))
(import "test" "dummy_five_params" (func $dummy_five_params (type 0)))

;; Globals
(global $var (mut i32) (i32.const 0))

;; Global getters
(func $get_global_var (result i32)
(global.get $var)
)

;; Test case functions
(func $five_params
(call $dummy_five_params (i32.const 0) (i32.const 1) (i32.const 2) (i32.const 3) (i32.const 4))
global.set $var
)

(start $five_params)
(export "five_params" (func $five_params))
(export "get_global_var" (func $get_global_var))
(memory (;0;) 1)
)

;; ----------------------------------------------
;; ==== GLOBALS, predicate, `target_fn_type` ====
;; WHAMM --> i32 count; wasm:opcode:call:before / target_fn_type == "import" / { count++; }
(assert_return (invoke "get_count") (i32.const 1)) ;; predicate is 'true'
;; WHAMM --> i32 count; wasm:opcode:call:before / target_fn_type == "local" / { count++; }
(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'

;; -------------------------------------------------
;; ==== GLOBALS, predicate, `target_imp_module` ====
;; WHAMM --> i32 count; wasm:opcode:call:before / target_imp_module == "test" / { count++; }
(assert_return (invoke "get_count") (i32.const 1)) ;; predicate is 'true'
;; WHAMM --> i32 count; wasm:opcode:call:before / target_imp_module == "wrong" / { count++; }
(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'

;; -----------------------------------------------
;; ==== GLOBALS, predicate, `target_fn_name` ====
;; TODO -- uncomment when we've merged in this PR: https://github.com/ejrgilbert/whamm/pull/112
;;;; WHAMM --> i32 count; wasm:opcode:call:before / target_fn_name == "wrong" / { count++; }
;;(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'
;;;; WHAMM --> i32 count; wasm:opcode:call:before / target_fn_name == "dummy_five_params" / { count++; }
;;(assert_return (invoke "get_count") (i32.const 1)) ;; predicate is 'true'

;; -----------------------------------------
;; ==== GLOBALS, body, `target_fn_type` ====
;; WHAMM --> i32 count; wasm:opcode:call:before { count = target_fn_type == "import" ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 1)) ;; condition is 'true'
;; WHAMM --> i32 count; wasm:opcode:call:before { count = target_fn_type == "local" ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'

;; --------------------------------------------
;; ==== GLOBALS, body, `target_imp_module` ====
;; WHAMM --> i32 count; wasm:opcode:call:before { count = target_imp_module == "test" ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 1)) ;; condition is 'true'

;; ------------------------------------------
;; ==== GLOBALS, body, `target_fn_name` ====
;; TODO -- uncomment when we've merged in this PR: https://github.com/ejrgilbert/whamm/pull/112
;;;; WHAMM --> i32 count; wasm:opcode:call:before { count = target_fn_name == "wrong" ? : 0; }
;;(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'
;;;; WHAMM --> i32 count; wasm:opcode:call:before { count = target_fn_name == "dummy_five_params" ? : 0; }
;;(assert_return (invoke "get_count") (i32.const 1)) ;; predicate is 'true'

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,14 @@

;; ---------------------------------
;; ==== IMMS, predicate, `imm0` ====
;; TODO
;; ----------------------------
;; ==== IMMS, body, `imm0` ====
;; TODO

;; ====================================
;; ---- `CALL`: imported functions ----
;; ====================================
;; WHAMM --> i32 count; wasm:opcode:call:before / imm0 == 0 / { count++; }
(assert_return (invoke "get_count") (i32.const 0)) ;; predicate is 'false'
;; WHAMM --> i32 count; wasm:opcode:call:before / imm0 == 1 / { count++; }
(assert_return (invoke "get_count") (i32.const 1)) ;; predicate is 'true'

;; ---------------------------------
;; ==== IMMS, predicate, `imm0` ====
;; TODO
;; ----------------------------
;; ==== IMMS, body, `imm0` ====
;; TODO
;; WHAMM --> i32 count; wasm:opcode:call:before { count = imm0 == 0 ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 0)) ;; condition is 'false'
;; WHAMM --> i32 count; wasm:opcode:call:before { count = imm0 == 1 ? 1 : 0; }
(assert_return (invoke "get_count") (i32.const 1)) ;; condition is 'true'
Loading

0 comments on commit 87ece61

Please sign in to comment.