feat(llvm): Implement Context Boxing pattern for cleaner APIs

Major improvement to reduce parameter explosion (15+ args → 3-4 contexts):
- Add LowerFnCtx/BlockCtx for grouping related parameters
- Add lightweight StrHandle/StrPtr newtypes for string safety
- Implement boxed API wrappers for boxcall/fields/invoke
- Add dev checks infrastructure (NYASH_DEV_CHECK_DISPATCH_ONLY_PHI)

Key achievements:
- lower_boxcall: 16 args → 7 args via boxed API
- fields/invoke: Similar parameter reduction
- BuilderCursor discipline enforced throughout
- String handle invariant: i64 across blocks, i8* only at call sites

Status:
- Internal migration in progress (fields → invoke → marshal)
- Full cutover pending due to borrow checker constraints
- dep_tree_min_string.o generation successful (sealed=ON)

Next: Complete internal migration before flipping to boxed APIs

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Selfhosting Dev
2025-09-13 00:07:38 +09:00
parent 8b48480844
commit 3bef7e8608
11 changed files with 436 additions and 35 deletions

View File

@ -11,6 +11,7 @@ use self::marshal as marshal_mod;
use self::invoke as invoke_mod;
use crate::mir::{function::MirFunction, BasicBlockId, ValueId};
use super::builder_cursor::BuilderCursor;
use super::ctx::{LowerFnCtx, BlockCtx};
// BoxCall lowering (large): mirrors existing logic; kept in one function for now
pub(in super::super) fn lower_boxcall<'ctx, 'b>(
@ -260,6 +261,39 @@ pub(in super::super) fn lower_boxcall<'ctx, 'b>(
}
}
// Boxed API: thin shim adapting LowerFnCtx/BlockCtx to the existing implementation.
pub(in super::super) fn lower_boxcall_boxed<'ctx, 'b>(
ctx: &mut LowerFnCtx<'ctx, 'b>,
blk: &BlockCtx<'ctx>,
dst: &Option<ValueId>,
box_val: &ValueId,
method: &str,
method_id: &Option<u16>,
args: &[ValueId],
entry_builder: &inkwell::builder::Builder<'ctx>,
) -> Result<(), String> {
// Optional dev check: ensure block is open for insertion
if ctx.dev_checks { ctx.cursor.assert_open(blk.cur_bid); }
lower_boxcall(
ctx.codegen,
ctx.cursor,
ctx.resolver,
blk.cur_bid,
ctx.func,
ctx.vmap,
dst,
box_val,
method,
method_id,
args,
ctx.box_type_ids.ok_or_else(|| "LowerFnCtx.box_type_ids missing".to_string())?,
entry_builder,
ctx.bb_map,
ctx.preds,
ctx.block_end_values,
)
}
fn coerce_to_type<'ctx>(
codegen: &CodegenContext<'ctx>,
val: inkwell::values::BasicValueEnum<'ctx>,