cranelift_codegen/legalizer/
table.rs1use crate::cursor::{Cursor, FuncCursor};
7use crate::ir::condcodes::IntCC;
8use crate::ir::immediates::Offset32;
9use crate::ir::{self, InstBuilder};
10use crate::isa::TargetIsa;
11
12pub fn expand_table_addr(
14 isa: &dyn TargetIsa,
15 inst: ir::Inst,
16 func: &mut ir::Function,
17 table: ir::Table,
18 index: ir::Value,
19 element_offset: Offset32,
20) {
21 let bound_gv = func.tables[table].bound_gv;
22 let index_ty = func.dfg.value_type(index);
23 let addr_ty = func.dfg.value_type(func.dfg.first_result(inst));
24 let mut pos = FuncCursor::new(func).at_inst(inst);
25 pos.use_srcloc(inst);
26
27 let bound = pos.ins().global_value(index_ty, bound_gv);
29
30 let oob = pos
32 .ins()
33 .icmp(IntCC::UnsignedGreaterThanOrEqual, index, bound);
34 pos.ins().trapnz(oob, ir::TrapCode::TableOutOfBounds);
35
36 let spectre_oob_cmp = if isa.flags().enable_table_access_spectre_mitigation() {
40 Some((index, bound))
41 } else {
42 None
43 };
44
45 compute_addr(
46 inst,
47 table,
48 addr_ty,
49 index,
50 index_ty,
51 element_offset,
52 pos.func,
53 spectre_oob_cmp,
54 );
55}
56
57fn compute_addr(
59 inst: ir::Inst,
60 table: ir::Table,
61 addr_ty: ir::Type,
62 mut index: ir::Value,
63 index_ty: ir::Type,
64 element_offset: Offset32,
65 func: &mut ir::Function,
66 spectre_oob_cmp: Option<(ir::Value, ir::Value)>,
67) {
68 let mut pos = FuncCursor::new(func).at_inst(inst);
69 pos.use_srcloc(inst);
70
71 if index_ty != addr_ty {
73 index = pos.ins().uextend(addr_ty, index);
74 }
75
76 let base_gv = pos.func.tables[table].base_gv;
78 let base = pos.ins().global_value(addr_ty, base_gv);
79
80 let element_size = pos.func.tables[table].element_size;
81 let mut offset;
82 let element_size: u64 = element_size.into();
83 if element_size == 1 {
84 offset = index;
85 } else if element_size.is_power_of_two() {
86 offset = pos
87 .ins()
88 .ishl_imm(index, i64::from(element_size.trailing_zeros()));
89 } else {
90 offset = pos.ins().imul_imm(index, element_size as i64);
91 }
92
93 let element_addr = if element_offset == Offset32::new(0) {
94 pos.ins().iadd(base, offset)
95 } else {
96 let imm: i64 = element_offset.into();
97 offset = pos.ins().iadd(base, offset);
98 pos.ins().iadd_imm(offset, imm)
99 };
100
101 let element_addr = if let Some((index, bound)) = spectre_oob_cmp {
102 let cond = pos
103 .ins()
104 .icmp(IntCC::UnsignedGreaterThanOrEqual, index, bound);
105 pos.ins().select_spectre_guard(cond, base, element_addr)
107 } else {
108 element_addr
109 };
110 let new_inst = pos.func.dfg.value_def(element_addr).inst().unwrap();
111
112 pos.func.dfg.replace_with_aliases(inst, new_inst);
113 pos.remove_inst();
114}