feat: less clone, avoid evaluating not depended thunk

This commit is contained in:
2025-06-18 09:32:00 +08:00
parent 3e9f0a72a0
commit d875951c09
14 changed files with 409 additions and 192 deletions

View File

@@ -4,38 +4,204 @@ use crate::ir::*;
use crate::ty::common as c;
use crate::ty::internal::Value;
use super::JITContext;
use super::{JITContext, ValueTag};
pub trait JITCompile {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc>;
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc>;
}
impl JITCompile for Attrs {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for List {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for HasAttr {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for BinOp {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
use ValueTag::*;
use BinOpKind::*;
let lhs = self.lhs.compile(ctx, func);
let rhs = self.rhs.compile(ctx, func);
let lhs_tag = ctx.get_tag(lhs);
let rhs_tag = ctx.get_tag(rhs);
let tag = ctx
.builder
.build_int_add(
lhs_tag.const_shl(ctx.helpers.const_int(8)),
rhs_tag,
"calc_tag",
)
.unwrap();
let ret = ctx.context.append_basic_block(func, "fallback");
let res = ctx
.builder
.build_alloca(ctx.helpers.value_type, "res_alloca")
.unwrap();
match self.kind {
Add => {
let int_int = ctx.context.append_basic_block(func, "int_int");
let int_float = ctx.context.append_basic_block(func, "int_float");
let float_int = ctx.context.append_basic_block(func, "float_int");
let float_float = ctx.context.append_basic_block(func, "float_float");
let fallback = ctx.context.append_basic_block(func, "fallback");
ctx.builder
.build_switch(
tag,
fallback,
&[
(
ctx.helpers.const_int(((Int as i64) << 8) + Int as i64),
int_int,
),
(
ctx.helpers.const_int(((Int as i64) << 8) + Float as i64),
int_float,
),
(
ctx.helpers.const_int(((Float as i64) << 8) + Int as i64),
float_int,
),
(
ctx.helpers.const_int(((Float as i64) << 8) + Float as i64),
float_float,
),
],
)
.unwrap();
ctx.builder.position_at_end(int_int);
let val = ctx
.builder
.build_int_add(ctx.get_int(lhs), ctx.get_int(rhs), "add")
.unwrap();
ctx.builder
.build_store(
res,
ctx.helpers.value_type.const_named_struct(&[
ctx.helpers.const_int(Int as i64).into(),
val.into(),
]),
)
.unwrap();
ctx.builder.position_at_end(int_float);
let val = ctx
.builder
.build_float_add(
ctx.builder
.build_signed_int_to_float(
ctx.get_int(lhs),
ctx.helpers.float_type,
"lhs_to_float",
)
.unwrap(),
ctx.get_float(rhs),
"add",
)
.unwrap();
ctx.builder
.build_store(
res,
ctx.helpers.value_type.const_named_struct(&[
ctx.helpers.const_int(Float as i64).into(),
val.into(),
]),
)
.unwrap();
ctx.builder.position_at_end(float_int);
let val = ctx
.builder
.build_float_add(
ctx.get_float(lhs),
ctx.builder
.build_signed_int_to_float(
ctx.get_int(rhs),
ctx.helpers.float_type,
"rhs_to_float",
)
.unwrap(),
"add",
)
.unwrap();
ctx.builder
.build_store(
res,
ctx.helpers.value_type.const_named_struct(&[
ctx.helpers.const_int(Float as i64).into(),
val.into(),
]),
)
.unwrap();
ctx.builder.position_at_end(int_int);
let val = ctx
.builder
.build_float_add(ctx.get_float(lhs), ctx.get_float(rhs), "add")
.unwrap();
ctx.builder
.build_store(
res,
ctx.helpers.value_type.const_named_struct(&[
ctx.helpers.const_int(Float as i64).into(),
val.into(),
]),
)
.unwrap();
ctx.builder.position_at_end(fallback);
}
Or => {
let bool_bool = ctx.context.append_basic_block(func, "int_int");
let fallback = ctx.context.append_basic_block(func, "fallback");
ctx.builder
.build_switch(
tag,
fallback,
&[
(
ctx.helpers.const_int(((Bool as i64) << 8) + Bool as i64),
bool_bool,
),
],
)
.unwrap();
ctx.builder.position_at_end(bool_bool);
let val = ctx
.builder
.build_or(ctx.get_bool(lhs), ctx.get_bool(rhs), "or")
.unwrap();
ctx.builder
.build_store(
res,
ctx.helpers.value_type.const_named_struct(&[
ctx.helpers.const_int(Bool as i64).into(),
val.into(),
]),
)
.unwrap();
ctx.builder.position_at_end(fallback);
}
_ => todo!()
}
ctx.builder.position_at_end(ret);
ctx.builder
.build_load(ctx.helpers.value_type, res, "load_res")
.unwrap()
.try_into()
.unwrap()
}
}
impl JITCompile for UnOp {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!();
let rhs = self.rhs.compile(ctx, func);
let tag = ctx.get_tag(rhs);
@@ -57,55 +223,55 @@ impl JITCompile for UnOp {
}
impl JITCompile for Select {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for If {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for LoadFunc {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Call {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Let {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for With {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Assert {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for ConcatStrings {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Const {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
use c::Const::*;
match self.val {
Bool(x) => ctx.helpers.new_bool(x),
@@ -117,37 +283,37 @@ impl JITCompile for Const {
}
impl JITCompile for String {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Var {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Arg {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for LetVar {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Thunk {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}
impl JITCompile for Path {
fn compile<'gc>(self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> {
todo!()
}
}