@@ -590,29 +590,41 @@ impl LiftIntrinsic {
590590 Self :: LiftFlatFloat64 => {
591591 let debug_log_fn = Intrinsic :: DebugLog . name ( ) ;
592592 let lift_flat_f64_fn = self . name ( ) ;
593- output. push_str ( & format ! ( "
594- function {lift_flat_f64_fn}(ctx) {{
595- {debug_log_fn}('[{lift_flat_f64_fn}()] args', {{ ctx }});
596- let val;
597-
598- if (ctx.useDirectParams) {{
599- if (ctx.params.length === 0) {{ throw new Error('expected at least one single f64 argument'); }}
600- val = ctx.params[0];
601- ctx.params = ctx.params.slice(1);
602- return [val, ctx];
603- }}
604-
605- if (ctx.storageLen !== undefined && ctx.storageLen < 8) {{
606- throw new Error(`insufficient storage ([${{ctx.storageLen}}] bytes) for lift (f64 requires 8 bytes)`);
607- }}
608-
609- val = new DataView(ctx.memory.buffer).getFloat64(ctx.storagePtr, true);
610- ctx.storagePtr += 8;
611- if (ctx.storageLen !== undefined) {{ ctx.storageLen -= 8; }}
612-
613- return [val, ctx];
614- }}
615- " ) ) ;
593+ uwriteln ! (
594+ output,
595+ r#"
596+ function {lift_flat_f64_fn}(ctx) {{
597+ {debug_log_fn}('[{lift_flat_f64_fn}()] args', {{ ctx }});
598+ let val;
599+
600+ if (ctx.useDirectParams) {{
601+ if (ctx.params.length === 0) {{
602+ throw new Error('expected at least one single f64 argument');
603+ }}
604+ val = ctx.params[0];
605+ ctx.params = ctx.params.slice(1);
606+
607+ if (ctx.inVariant) {{
608+ const dv = new DataView(new ArrayBuffer(8));
609+ dv.setBigInt64(0, val);
610+ val = dv.getFloat64(0);
611+ }}
612+
613+ return [val, ctx];
614+ }}
615+
616+ if (ctx.storageLen !== undefined && ctx.storageLen < 8) {{
617+ throw new Error(`insufficient storage ([${{ctx.storageLen}}] bytes) for lift (f64 requires 8 bytes)`);
618+ }}
619+
620+ val = new DataView(ctx.memory.buffer).getFloat64(ctx.storagePtr, true);
621+ ctx.storagePtr += 8;
622+ if (ctx.storageLen !== undefined) {{ ctx.storageLen -= 8; }}
623+
624+ return [val, ctx];
625+ }}
626+ "#
627+ ) ;
616628 }
617629
618630 Self :: LiftFlatChar => {
@@ -797,11 +809,21 @@ impl LiftIntrinsic {
797809 let lift_u8 = Self :: LiftFlatU8 . name ( ) ;
798810 let lift_u16 = Self :: LiftFlatU16 . name ( ) ;
799811 let lift_u32 = Self :: LiftFlatU32 . name ( ) ;
812+ let lift_f64 = Self :: LiftFlatFloat64 . name ( ) ;
813+
800814 output. push_str ( & format ! ( r#"
801- function {lift_flat_variant_fn}(casesAndLiftFns) {{
815+ function {lift_flat_variant_fn}(meta) {{
816+ const {{
817+ caseMetas,
818+ variantSize32,
819+ variantAlign32,
820+ variantPayloadOffset32,
821+ variantFlatCount,
822+ isEnum,
823+ }} = meta;
824+
802825 return function {lift_flat_variant_fn}Inner(ctx) {{
803826 {debug_log_fn}('[{lift_flat_variant_fn}()] args', {{ ctx }});
804-
805827 const origUseParams = ctx.useDirectParams;
806828
807829 // If we're in the process of lifting a variant, we note
@@ -812,8 +834,8 @@ impl LiftIntrinsic {
812834 let caseIdx;
813835 let liftRes;
814836 const originalPtr = ctx.storagePtr;
815- const numCases = casesAndLiftFns .length;
816- if (casesAndLiftFns .length < 256) {{
837+ const numCases = caseMetas .length;
838+ if (caseMetas .length < 256) {{
817839 liftRes = {lift_u8}(ctx);
818840 }} else if (numCases >= 256 && numCases < 65536) {{
819841 liftRes = {lift_u16}(ctx);
@@ -825,11 +847,20 @@ impl LiftIntrinsic {
825847 caseIdx = liftRes[0];
826848 ctx = liftRes[1];
827849
828- const [ tag, liftFn, size32, align32, payloadOffset32, caseFlatCount, variantFlatCount ] = casesAndLiftFns[caseIdx];
829- if (payloadOffset32 === undefined) {{ throw new Error('unexpectedly missing payload offset'); }}
850+ const [
851+ tag,
852+ liftFn,
853+ caseSize32,
854+ caseAlign32,
855+ caseFlatCount,
856+ ] = caseMetas[caseIdx];
857+
858+ if (variantPayloadOffset32 === undefined) {{
859+ throw new Error('unexpectedly missing payload offset');
860+ }}
830861
831862 if (originalPtr !== undefined) {{
832- ctx.storagePtr = originalPtr + payloadOffset32 ;
863+ ctx.storagePtr = originalPtr + variantPayloadOffset32 ;
833864 }}
834865
835866 let val;
@@ -838,28 +869,37 @@ impl LiftIntrinsic {
838869 // NOTE: here we need to move past the entire object in memory
839870 // despite moving to the payload which we now know is missing/unnecessary
840871 if (originalPtr !== undefined) {{
841- ctx.storagePtr = originalPtr + size32;
872+ // NOTE: THIS IS ZERO OTHERWISE
873+ ctx.storagePtr = originalPtr + variantSize32;
842874 }}
843875 }} else {{
876+ if (ctx.ctxUseDirectParams && ctx.params && liftFn !== {lift_f64} && typeof ctx.params[0] === 'bigint') {{
877+ if (ctx.params[0] > BigInt(Number.MAX_SAFE_INTEGER)) {{
878+ throw new Error(`invalid value, reinterpreted i32/f32 too large: [${{ctx.params[0]}}]`);
879+ }}
880+ ctx.params[0] = Number(ctx.params[0]);
881+ }}
882+
844883 const [newVal, newCtx] = liftFn(ctx);
845884 val = {{ tag, val: newVal }};
846885 ctx = newCtx;
847886
848887 // NOTE: Padding can be left over after doing the lift if it was less than
849888 // space left for the payload normally.
850889 if (originalPtr !== undefined) {{
851- ctx.storagePtr = Math.max(ctx.storagePtr, originalPtr + size32 );
890+ ctx.storagePtr = Math.max(ctx.storagePtr, originalPtr + caseSize32 );
852891 }}
853892 }}
854893
855894 if (origUseParams) {{
856- if (caseFlatCount === undefined || variantFlatCount === undefined) {{
857- throw new Error('variant flat count metadata is missing');
858- }}
859- if (caseFlatCount === null || variantFlatCount === null) {{
895+ if (variantFlatCount === undefined || variantFlatCount === null) {{
860896 throw new Error('cannot lift variant with unknown flat count');
861897 }}
862- const remainingPayloadParams = variantFlatCount - 1 - caseFlatCount;
898+ if (caseFlatCount === undefined || caseFlatCount === null) {{
899+ throw new Error('cannot lift case with unknown flat count');
900+ }}
901+ // NOTE: enums can be tightly packed and do not have a descriminant
902+ const remainingPayloadParams = variantFlatCount - caseFlatCount - (isEnum ? 0 : 1);
863903 if (remainingPayloadParams < 0) {{
864904 throw new Error(`invalid variant flat count metadata`);
865905 }}
@@ -870,8 +910,8 @@ impl LiftIntrinsic {
870910 }}
871911
872912 if (ctx.storagePtr !== undefined) {{
873- const rem = ctx.storagePtr % align32 ;
874- if (rem !== 0) {{ ctx.storagePtr += align32 - rem; }}
913+ const rem = ctx.storagePtr % variantAlign32 ;
914+ if (rem !== 0) {{ ctx.storagePtr += variantAlign32 - rem; }}
875915 }}
876916
877917 ctx.inVariant = wasInVariant;
@@ -1040,10 +1080,12 @@ impl LiftIntrinsic {
10401080 let lift_flat_enum_fn = self . name ( ) ;
10411081 output. push_str ( & format ! (
10421082 r#"
1043- function {lift_flat_enum_fn}(casesAndLiftFns) {{
1083+ function {lift_flat_enum_fn}(meta) {{
1084+ meta.isEnum = true;
1085+ const f = {lift_variant}(meta);
10441086 return function {lift_flat_enum_fn}Inner(ctx) {{
10451087 {debug_log_fn}('[{lift_flat_enum_fn}()] args', {{ ctx }});
1046- const res = {lift_variant}(casesAndLiftFns) (ctx);
1088+ const res = f (ctx);
10471089 res[0] = res[0].tag;
10481090 return res;
10491091 }}
@@ -1058,10 +1100,11 @@ impl LiftIntrinsic {
10581100 let lift_flat_option_fn = self . name ( ) ;
10591101 output. push_str ( & format ! (
10601102 r#"
1061- function {lift_flat_option_fn}(casesAndLiftFns) {{
1103+ function {lift_flat_option_fn}(meta) {{
1104+ const f = {lift_variant}(meta);
10621105 return function {lift_flat_option_fn}Inner(ctx) {{
10631106 {debug_log_fn}('[{lift_flat_option_fn}()] args', {{ ctx }});
1064- return {lift_variant}(casesAndLiftFns) (ctx);
1107+ return f (ctx);
10651108 }}
10661109 }}
10671110 "#
@@ -1074,10 +1117,11 @@ impl LiftIntrinsic {
10741117 let lift_flat_result_fn = self . name ( ) ;
10751118 output. push_str ( & format ! (
10761119 r#"
1077- function {lift_flat_result_fn}(casesAndLiftFns) {{
1120+ function {lift_flat_result_fn}(meta) {{
1121+ const f = {lift_variant}(meta);
10781122 return function {lift_flat_result_fn}Inner(ctx) {{
10791123 {debug_log_fn}('[{lift_flat_result_fn}()] args', {{ ctx }});
1080- return {lift_variant}(casesAndLiftFns) (ctx);
1124+ return f (ctx);
10811125 }}
10821126 }}
10831127 "#
0 commit comments