Skip to main content

pepl_codegen/
gas.rs

1//! Gas-metering instrumentation.
2//!
3//! Injects a `gas_tick` call at:
4//! - Every `for` loop iteration header
5//! - Every action / function call site
6//! - Every `update()` call boundary
7//!
8//! When the counter exceeds the limit, the runtime traps.
9
10use wasm_encoder::{Function, Instruction};
11
12use crate::types::{GLOBAL_GAS, GLOBAL_GAS_LIMIT, IMPORT_TRAP};
13
14/// Emit instructions that increment the gas counter and trap if exhausted.
15///
16/// Equivalent pseudo-code:
17/// ```text
18/// gas += 1
19/// if gas > gas_limit { trap("gas exhausted") }
20/// ```
21pub fn emit_gas_tick(f: &mut Function, trap_msg_ptr: u32, trap_msg_len: u32) {
22    // gas += 1
23    f.instruction(&Instruction::GlobalGet(GLOBAL_GAS));
24    f.instruction(&Instruction::I32Const(1));
25    f.instruction(&Instruction::I32Add);
26    f.instruction(&Instruction::GlobalSet(GLOBAL_GAS));
27
28    // if gas > gas_limit → trap
29    f.instruction(&Instruction::GlobalGet(GLOBAL_GAS));
30    f.instruction(&Instruction::GlobalGet(GLOBAL_GAS_LIMIT));
31    f.instruction(&Instruction::I32GtU);
32    f.instruction(&Instruction::If(wasm_encoder::BlockType::Empty));
33    f.instruction(&Instruction::I32Const(trap_msg_ptr as i32));
34    f.instruction(&Instruction::I32Const(trap_msg_len as i32));
35    f.instruction(&Instruction::Call(IMPORT_TRAP));
36    f.instruction(&Instruction::Unreachable);
37    f.instruction(&Instruction::End);
38}