wasmer_compiler_cranelift/
table.rs1use cranelift_codegen::cursor::FuncCursor;
2use cranelift_codegen::ir::{self, InstBuilder, condcodes::IntCC, immediates::Imm64};
3use cranelift_frontend::FunctionBuilder;
4
5use crate::translator::{MemoryAliasRegion, set_memflags_alias_region};
6
7#[derive(Clone, Debug)]
9pub enum TableSize {
10 Static {
12 bound: u32,
14 },
15 Dynamic {
17 bound_gv: ir::GlobalValue,
20 },
21}
22
23impl TableSize {
24 pub fn bound(&self, mut pos: FuncCursor, index_ty: ir::Type) -> ir::Value {
26 match *self {
27 Self::Static { bound } => pos.ins().iconst(index_ty, Imm64::new(i64::from(bound))),
28 Self::Dynamic { bound_gv } => pos.ins().global_value(index_ty, bound_gv),
29 }
30 }
31}
32
33#[derive(Clone, Debug)]
35pub struct TableData {
36 pub base_gv: ir::GlobalValue,
38
39 pub base_offset: i32,
41
42 pub bound: TableSize,
44
45 pub element_size: u32,
47
48 pub inline_anyfunc: bool,
50}
51
52impl TableData {
53 pub fn prepare_table_addr(
56 &self,
57 pos: &mut FunctionBuilder,
58 mut index: ir::Value,
59 addr_ty: ir::Type,
60 enable_table_access_spectre_mitigation: bool,
61 ) -> (ir::Value, ir::MemFlagsData) {
62 let index_ty = pos.func.dfg.value_type(index);
63
64 let bound = self.bound.bound(pos.cursor(), index_ty);
66
67 let oob = pos
69 .ins()
70 .icmp(IntCC::UnsignedGreaterThanOrEqual, index, bound);
71
72 if !enable_table_access_spectre_mitigation {
73 pos.ins().trapnz(oob, crate::TRAP_TABLE_OUT_OF_BOUNDS);
74 }
75
76 if index_ty != addr_ty {
78 index = pos.ins().uextend(addr_ty, index);
79 }
80
81 let mut base = pos.ins().global_value(addr_ty, self.base_gv);
83 if self.base_offset != 0 {
84 base = pos.ins().iadd_imm(base, i64::from(self.base_offset));
85 }
86
87 let element_size = self.element_size;
88 let offset = if element_size == 1 {
89 index
90 } else if element_size.is_power_of_two() {
91 pos.ins()
92 .ishl_imm(index, i64::from(element_size.trailing_zeros()))
93 } else {
94 pos.ins().imul_imm(index, element_size as i64)
95 };
96
97 let element_addr = pos.ins().iadd(base, offset);
98
99 let mut base_flags = ir::MemFlagsData::new().with_aligned();
100 set_memflags_alias_region(pos.func, &mut base_flags, MemoryAliasRegion::Table);
101 if enable_table_access_spectre_mitigation {
102 let zero = pos.ins().iconst(addr_ty, 0);
106 (
107 pos.ins().select_spectre_guard(oob, zero, element_addr),
108 base_flags.with_trap_code(Some(crate::TRAP_TABLE_OUT_OF_BOUNDS)),
109 )
110 } else {
111 (element_addr, base_flags.with_trap_code(None))
112 }
113 }
114}