diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs')
-rw-r--r-- | third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs b/third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs new file mode 100644 index 0000000000..5c7a72b45c --- /dev/null +++ b/third_party/rust/cranelift-codegen/src/legalizer/globalvalue.rs @@ -0,0 +1,140 @@ +//! Legalization of global values. +//! +//! This module exports the `expand_global_value` function which transforms a `global_value` +//! instruction into code that depends on the kind of global value referenced. + +use crate::cursor::{Cursor, FuncCursor}; +use crate::flowgraph::ControlFlowGraph; +use crate::ir::{self, InstBuilder}; +use crate::isa::TargetIsa; + +/// Expand a `global_value` instruction according to the definition of the global value. +pub fn expand_global_value( + inst: ir::Inst, + func: &mut ir::Function, + _cfg: &mut ControlFlowGraph, + isa: &dyn TargetIsa, +) { + // Unpack the instruction. + let gv = match func.dfg[inst] { + ir::InstructionData::UnaryGlobalValue { + opcode, + global_value, + } => { + debug_assert_eq!(opcode, ir::Opcode::GlobalValue); + global_value + } + _ => panic!("Wanted global_value: {}", func.dfg.display_inst(inst, None)), + }; + + match func.global_values[gv] { + ir::GlobalValueData::VMContext => vmctx_addr(inst, func), + ir::GlobalValueData::IAddImm { + base, + offset, + global_type, + } => iadd_imm_addr(inst, func, base, offset.into(), global_type), + ir::GlobalValueData::Load { + base, + offset, + global_type, + readonly, + } => load_addr(inst, func, base, offset, global_type, readonly, isa), + ir::GlobalValueData::Symbol { tls, .. } => symbol(inst, func, gv, isa, tls), + } +} + +/// Expand a `global_value` instruction for a vmctx global. +fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function) { + // Get the value representing the `vmctx` argument. + let vmctx = func + .special_param(ir::ArgumentPurpose::VMContext) + .expect("Missing vmctx parameter"); + + // Replace the `global_value` instruction's value with an alias to the vmctx arg. + let result = func.dfg.first_result(inst); + func.dfg.clear_results(inst); + func.dfg.change_to_alias(result, vmctx); + func.layout.remove_inst(inst); +} + +/// Expand a `global_value` instruction for an iadd_imm global. +fn iadd_imm_addr( + inst: ir::Inst, + func: &mut ir::Function, + base: ir::GlobalValue, + offset: i64, + global_type: ir::Type, +) { + let mut pos = FuncCursor::new(func).at_inst(inst); + + // Get the value for the lhs. For tidiness, expand VMContext here so that we avoid + // `vmctx_addr` which creates an otherwise unneeded value alias. + let lhs = if let ir::GlobalValueData::VMContext = pos.func.global_values[base] { + pos.func + .special_param(ir::ArgumentPurpose::VMContext) + .expect("Missing vmctx parameter") + } else { + pos.ins().global_value(global_type, base) + }; + + // Simply replace the `global_value` instruction with an `iadd_imm`, reusing the result value. + pos.func.dfg.replace(inst).iadd_imm(lhs, offset); +} + +/// Expand a `global_value` instruction for a load global. +fn load_addr( + inst: ir::Inst, + func: &mut ir::Function, + base: ir::GlobalValue, + offset: ir::immediates::Offset32, + global_type: ir::Type, + readonly: bool, + isa: &dyn TargetIsa, +) { + // We need to load a pointer from the `base` global value, so insert a new `global_value` + // instruction. This depends on the iterative legalization loop. Note that the IR verifier + // detects any cycles in the `load` globals. + let ptr_ty = isa.pointer_type(); + let mut pos = FuncCursor::new(func).at_inst(inst); + pos.use_srcloc(inst); + + // Get the value for the base. For tidiness, expand VMContext here so that we avoid + // `vmctx_addr` which creates an otherwise unneeded value alias. + let base_addr = if let ir::GlobalValueData::VMContext = pos.func.global_values[base] { + pos.func + .special_param(ir::ArgumentPurpose::VMContext) + .expect("Missing vmctx parameter") + } else { + pos.ins().global_value(ptr_ty, base) + }; + + // Global-value loads are always notrap and aligned. They may be readonly. + let mut mflags = ir::MemFlags::trusted(); + if readonly { + mflags.set_readonly(); + } + + // Perform the load. + pos.func + .dfg + .replace(inst) + .load(global_type, mflags, base_addr, offset); +} + +/// Expand a `global_value` instruction for a symbolic name global. +fn symbol( + inst: ir::Inst, + func: &mut ir::Function, + gv: ir::GlobalValue, + isa: &dyn TargetIsa, + tls: bool, +) { + let ptr_ty = isa.pointer_type(); + + if tls { + func.dfg.replace(inst).tls_value(ptr_ty, gv); + } else { + func.dfg.replace(inst).symbol_value(ptr_ty, gv); + } +} |