Created
October 26, 2023 07:42
-
-
Save playXE/e010fbea17a7439d2ca8b9c6e814eb3a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::rc::Rc; | |
use b3::{ValueRep, Reg, BasicBlockBuilder}; | |
use macroassembler::{jit::{gpr_info::*, helpers::AssemblyHelpers}, assembler::{abstract_macro_assembler::Address, TargetMacroAssembler}}; | |
pub fn tail_call(bb: &mut b3::BasicBlockBuilder, callee: b3::ValueId, args: &[b3::ValueId]) { | |
let patchpoint = bb.patchpoint(b3::Type::Void); | |
bb.procedure.patchpoint_effects_mut(patchpoint).terminal = true; | |
bb.procedure.patchpoint_effects_mut(patchpoint).exit_sideways = true; | |
for (i, &arg) in args.iter().enumerate() { | |
let rep = match i { | |
0 => ValueRep::reg(Reg::new_gpr(ARGUMENT_GPR0)), | |
1 => ValueRep::reg(Reg::new_gpr(ARGUMENT_GPR1)), | |
2 => ValueRep::reg(Reg::new_gpr(ARGUMENT_GPR2)), | |
3 => ValueRep::reg(Reg::new_gpr(ARGUMENT_GPR3)), | |
#[cfg(not(windows))] | |
4 => ValueRep::reg(Reg::new_gpr(ARGUMENT_GPR4)), | |
#[cfg(not(windows))] | |
5 => ValueRep::reg(Reg::new_gpr(ARGUMENT_GPR5)), | |
_ => todo!() | |
}; | |
bb.procedure.stackmap_append(patchpoint, arg, rep); | |
} | |
bb.procedure.stackmap_append(patchpoint, callee, ValueRep::new(b3::ValueRepKind::WarmAny)); | |
bb.procedure.stackmap_set_generator(patchpoint, Rc::new(|jit, params| { | |
let callee = params.last().unwrap(); | |
jit.emit_function_epilogue(); | |
if callee.is_reg() { | |
jit.far_jump(callee.get_reg().gpr()); | |
} else if callee.is_stack() { | |
jit.far_jump(Address::new(TargetMacroAssembler::FRAME_POINTER_REGISTER, callee.offset_from_fp() as _)); | |
} else if callee.is_stack_argument() { | |
jit.far_jump(Address::new(TargetMacroAssembler::STACK_POINTER_REGISTER, callee.offset_from_sp() as _)); | |
} else if callee.is_constant() { | |
jit.mov(callee.value(), TargetMacroAssembler::SCRATCH_REGISTER); | |
jit.far_jump(TargetMacroAssembler::SCRATCH_REGISTER); | |
} else { | |
unreachable!(); | |
} | |
})); | |
} | |
fn main() { | |
let mut proc = b3::Procedure::new(b3::Options::default()); | |
let entry = proc.add_block(1.0); | |
let mut bb = BasicBlockBuilder::new(&mut proc, entry); | |
let callee = bb.argument(Reg::new_gpr(ARGUMENT_GPR0), b3::Type::Int64); | |
let x1 = bb.argument(Reg::new_gpr(ARGUMENT_GPR1), b3::Type::Int32); | |
let y2 = bb.const32(42); | |
tail_call(&mut bb, callee, &[x1, y2]); | |
let code = b3::compile(proc); | |
println!("{}", code.disassembly()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment