@@ -5,6 +5,7 @@ use crate::decl::*;
55use crate :: defs:: * ;
66use crate :: expr:: * ;
77use crate :: DeclTable ;
8+ use crate :: TypeID ;
89
910use std:: convert:: TryFrom ;
1011
@@ -822,6 +823,7 @@ impl<'ctx> LLVMJITState<'ctx> {
822823
823824 // Set up local variable map: name → alloca pointer.
824825 let mut variables: HashMap < String , PointerValue < ' ctx > > = HashMap :: new ( ) ;
826+ let mut variable_types: HashMap < String , TypeID > = HashMap :: new ( ) ;
825827 let mut let_bindings: HashSet < String > = HashSet :: new ( ) ;
826828
827829 // Load closure variables (captured variables).
@@ -850,6 +852,7 @@ impl<'ctx> LLVMJITState<'ctx> {
850852 . unwrap ( ) ;
851853 self . builder . build_store ( alloca, var_ptr) . unwrap ( ) ;
852854 variables. insert ( cv. name . to_string ( ) , alloca) ;
855+ variable_types. insert ( cv. name . to_string ( ) , cv. ty ) ;
853856 // closure vars are treated like var bindings (pointer-indirected)
854857 }
855858
@@ -878,13 +881,15 @@ impl<'ctx> LLVMJITState<'ctx> {
878881 . unwrap ( ) ;
879882 self . builder . build_store ( alloca, param_val) . unwrap ( ) ;
880883 variables. insert ( param. name . to_string ( ) , alloca) ;
884+ variable_types. insert ( param. name . to_string ( ) , ty) ;
881885 let_bindings. insert ( param. name . to_string ( ) ) ;
882886 }
883887
884888 let mut trans = FunctionTranslator {
885889 state : self ,
886890 function,
887891 variables,
892+ variable_types,
888893 let_bindings,
889894 globals_base,
890895 output_ptr,
@@ -965,6 +970,7 @@ struct FunctionTranslator<'a, 'ctx> {
965970 /// name → alloca. For let-bindings the alloca holds the value directly.
966971 /// For var-bindings the alloca holds a pointer to the actual stack slot.
967972 variables : HashMap < String , PointerValue < ' ctx > > ,
973+ variable_types : HashMap < String , TypeID > ,
968974 let_bindings : HashSet < String > ,
969975 globals_base : PointerValue < ' ctx > ,
970976 output_ptr : Option < PointerValue < ' ctx > > ,
@@ -1313,6 +1319,48 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
13131319 }
13141320 }
13151321
1322+ fn representation_type ( & self , expr : ExprID , decl : & FuncDecl ) -> crate :: TypeID {
1323+ match & decl. arena . exprs [ expr] {
1324+ Expr :: Id ( name) => self
1325+ . variable_types
1326+ . get ( name. as_str ( ) )
1327+ . copied ( )
1328+ . or_else ( || {
1329+ self . decls . find ( * name) . iter ( ) . find_map ( |decl| {
1330+ if let crate :: Decl :: Global { ty, .. } = decl {
1331+ Some ( * ty)
1332+ } else {
1333+ None
1334+ }
1335+ } )
1336+ } )
1337+ . unwrap_or ( decl. types [ expr] ) ,
1338+ Expr :: ArrayIndex ( arr_id, _) => match & * self . representation_type ( * arr_id, decl) {
1339+ crate :: Type :: Array ( elem, _) | crate :: Type :: Slice ( elem) => * elem,
1340+ _ => decl. types [ expr] ,
1341+ } ,
1342+ _ => decl. types [ expr] ,
1343+ }
1344+ }
1345+
1346+ fn wrap_for_expected_slice (
1347+ & self ,
1348+ val : BasicValueEnum < ' ctx > ,
1349+ expected_ty : crate :: TypeID ,
1350+ actual_expr : ExprID ,
1351+ decl : & FuncDecl ,
1352+ ) -> BasicValueEnum < ' ctx > {
1353+ if matches ! ( & * expected_ty, crate :: Type :: Slice ( _) ) {
1354+ self . wrap_as_slice (
1355+ val. into_pointer_value ( ) ,
1356+ self . representation_type ( actual_expr, decl) ,
1357+ )
1358+ . into ( )
1359+ } else {
1360+ val
1361+ }
1362+ }
1363+
13161364 fn gen_zero_mem ( & self , dst : PointerValue < ' ctx > , size : usize ) {
13171365 self . emit_memzero ( dst, size) ;
13181366 }
@@ -1620,9 +1668,11 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
16201668 let ( name, init_id) = ( * name, * init_id) ;
16211669 let ty = decl. types [ expr] ;
16221670 let init_val = self . translate_expr ( init_id, decl) ;
1671+ let init_val = self . wrap_for_expected_slice ( init_val, ty, init_id, decl) ;
16231672 let alloca = self . entry_alloca ( ty. llvm_basic_type ( self . ctx ( ) ) , & * name) ;
16241673 self . builder ( ) . build_store ( alloca, init_val) . unwrap ( ) ;
16251674 self . variables . insert ( name. to_string ( ) , alloca) ;
1675+ self . variable_types . insert ( name. to_string ( ) , ty) ;
16261676 self . let_bindings . insert ( name. to_string ( ) ) ;
16271677 init_val
16281678 }
@@ -1644,6 +1694,7 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
16441694 self . builder ( ) . build_store ( alloca, zero) . unwrap ( ) ;
16451695 }
16461696 self . variables . insert ( name. to_string ( ) , alloca) ;
1697+ self . variable_types . insert ( name. to_string ( ) , ty) ;
16471698 self . let_bindings . insert ( name. to_string ( ) ) ;
16481699 } else {
16491700 // Pointer/struct var: allocate byte storage + ptr alloca.
@@ -1655,9 +1706,11 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
16551706 let alloca = self . entry_alloca ( self . ptr_ty ( ) . into ( ) , & * name) ;
16561707 self . builder ( ) . build_store ( alloca, storage) . unwrap ( ) ;
16571708 self . variables . insert ( name. to_string ( ) , alloca) ;
1709+ self . variable_types . insert ( name. to_string ( ) , ty) ;
16581710
16591711 if let Some ( init_id) = init_id {
16601712 let init_val = self . translate_expr ( init_id, decl) ;
1713+ let init_val = self . wrap_for_expected_slice ( init_val, ty, init_id, decl) ;
16611714 self . gen_copy ( ty, storage, init_val) ;
16621715 } else {
16631716 self . gen_zero_mem ( storage, sz) ;
@@ -1772,6 +1825,7 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
17721825 // Save variable scope — declarations inside this block
17731826 // shadow outer names only for the duration of the block.
17741827 let saved_vars = self . variables . clone ( ) ;
1828+ let saved_types = self . variable_types . clone ( ) ;
17751829 let saved_lets = self . let_bindings . clone ( ) ;
17761830 let mut result = self . zero_i32 ( ) ;
17771831 for e in & exprs {
@@ -1781,6 +1835,7 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
17811835 result = self . translate_expr ( * e, decl) ;
17821836 }
17831837 self . variables = saved_vars;
1838+ self . variable_types = saved_types;
17841839 self . let_bindings = saved_lets;
17851840 result
17861841 }
@@ -1927,6 +1982,8 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
19271982 self . builder ( ) . build_store ( loop_alloca, start_val) . unwrap ( ) ;
19281983 // Treat as let binding (holds value directly).
19291984 self . variables . insert ( var. to_string ( ) , loop_alloca) ;
1985+ self . variable_types
1986+ . insert ( var. to_string ( ) , crate :: types:: mk_type ( crate :: Type :: Int32 ) ) ;
19301987 self . let_bindings . insert ( var. to_string ( ) ) ;
19311988
19321989 let header_bb = self . append_bb ( "for_header" ) ;
@@ -2408,7 +2465,7 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
24082465 }
24092466 }
24102467 // f32x4 full assignment: v = expr → store vector to alloca
2411- let t = decl . types [ lhs_id] ;
2468+ let t = self . representation_type ( lhs_id, decl ) ;
24122469 if matches ! ( * t, crate :: Type :: Float32x4 ) {
24132470 if let Expr :: Id ( name) = & decl. arena . exprs [ lhs_id] {
24142471 if let Some ( & alloca) = self . variables . get ( & * * name) {
@@ -2420,6 +2477,7 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
24202477 }
24212478 let lhs_addr = self . translate_lvalue ( lhs_id, decl) ;
24222479 let rhs_val = self . translate_expr ( rhs_id, decl) ;
2480+ let rhs_val = self . wrap_for_expected_slice ( rhs_val, t, rhs_id, decl) ;
24232481 self . gen_copy ( t, lhs_addr, rhs_val) ;
24242482 rhs_val
24252483 }
@@ -2896,7 +2954,7 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
28962954 let arg_val = self . translate_expr ( * arg_id, decl) ;
28972955 let param_ty = callee_decl. params [ i] . ty . unwrap ( ) ;
28982956 if matches ! ( & * param_ty, crate :: Type :: Slice ( _) ) {
2899- let actual_ty = decl . types [ * arg_id] ;
2957+ let actual_ty = self . representation_type ( * arg_id, decl ) ;
29002958 match & * actual_ty {
29012959 crate :: Type :: Slice ( _) => {
29022960 // Already a fat pointer: load data_ptr and len.
@@ -3025,8 +3083,10 @@ impl<'a, 'ctx> FunctionTranslator<'a, 'ctx> {
30253083 for ( i, arg_id) in arg_ids. iter ( ) . enumerate ( ) {
30263084 let arg_val = self . translate_expr ( * arg_id, decl) ;
30273085 if i < param_types. len ( ) && is_slice ( param_types[ i] ) {
3028- let wrapped =
3029- self . wrap_as_slice ( arg_val. into_pointer_value ( ) , decl. types [ * arg_id] ) ;
3086+ let wrapped = self . wrap_as_slice (
3087+ arg_val. into_pointer_value ( ) ,
3088+ self . representation_type ( * arg_id, decl) ,
3089+ ) ;
30303090 args. push ( wrapped. into ( ) ) ;
30313091 } else {
30323092 let pi = arg_start + i;
0 commit comments