@@ -1408,11 +1408,22 @@ fn resolveCallingConventionValues(
14081408 },
14091409 .wasm_mvp = > {
14101410 for (fn_info .param_types .get (ip )) | ty | {
1411- const ty_classes = abi .classifyType (Type .fromInterned (ty ), zcu );
1412- for (ty_classes ) | class | {
1413- if (class == .none ) continue ;
1414- try args .append (.{ .local = .{ .value = result .local_index , .references = 1 } });
1415- result .local_index += 1 ;
1411+ if (! Type .fromInterned (ty ).hasRuntimeBitsIgnoreComptime (zcu )) {
1412+ continue ;
1413+ }
1414+ switch (abi .classifyType (.fromInterned (ty ), zcu )) {
1415+ .direct = > | scalar_ty | if (! abi .lowerAsDoubleI64 (scalar_ty , zcu )) {
1416+ try args .append (.{ .local = .{ .value = result .local_index , .references = 1 } });
1417+ result .local_index += 1 ;
1418+ } else {
1419+ try args .append (.{ .local = .{ .value = result .local_index , .references = 1 } });
1420+ try args .append (.{ .local = .{ .value = result .local_index + 1 , .references = 1 } });
1421+ result .local_index += 2 ;
1422+ },
1423+ .indirect = > {
1424+ try args .append (.{ .local = .{ .value = result .local_index , .references = 1 } });
1425+ result .local_index += 1 ;
1426+ },
14161427 }
14171428 }
14181429 },
@@ -1428,14 +1439,13 @@ pub fn firstParamSRet(
14281439 zcu : * const Zcu ,
14291440 target : * const std.Target ,
14301441) bool {
1442+ if (! return_type .hasRuntimeBitsIgnoreComptime (zcu )) return false ;
14311443 switch (cc ) {
14321444 .@"inline" = > unreachable ,
14331445 .auto = > return isByRef (return_type , zcu , target ),
1434- .wasm_mvp = > {
1435- const ty_classes = abi .classifyType (return_type , zcu );
1436- if (ty_classes [0 ] == .indirect ) return true ;
1437- if (ty_classes [0 ] == .direct and ty_classes [1 ] == .direct ) return true ;
1438- return false ;
1446+ .wasm_mvp = > switch (abi .classifyType (return_type , zcu )) {
1447+ .direct = > | scalar_ty | return abi .lowerAsDoubleI64 (scalar_ty , zcu ),
1448+ .indirect = > return true ,
14391449 },
14401450 else = > return false ,
14411451 }
@@ -1449,34 +1459,27 @@ fn lowerArg(cg: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WV
14491459 }
14501460
14511461 const zcu = cg .pt .zcu ;
1452- const ty_classes = abi .classifyType (ty , zcu );
1453- assert (ty_classes [0 ] != .none );
1454- switch (ty .zigTypeTag (zcu )) {
1455- .@"struct" , .@"union" = > {
1456- if (ty_classes [0 ] == .indirect ) {
1457- return cg .lowerToStack (value );
1458- }
1459- assert (ty_classes [0 ] == .direct );
1460- const scalar_type = abi .scalarType (ty , zcu );
1461- switch (value ) {
1462- .nav_ref , .stack_offset = > _ = try cg .load (value , scalar_type , 0 ),
1463- .dead = > unreachable ,
1464- else = > try cg .emitWValue (value ),
1465- }
1466- },
1467- .int , .float = > {
1468- if (ty_classes [1 ] == .none ) {
1462+
1463+ switch (abi .classifyType (ty , zcu )) {
1464+ .direct = > | scalar_type | if (! abi .lowerAsDoubleI64 (scalar_type , zcu )) {
1465+ if (! isByRef (ty , zcu , cg .target )) {
14691466 return cg .lowerToStack (value );
1467+ } else {
1468+ switch (value ) {
1469+ .nav_ref , .stack_offset = > _ = try cg .load (value , scalar_type , 0 ),
1470+ .dead = > unreachable ,
1471+ else = > try cg .emitWValue (value ),
1472+ }
14701473 }
1471- assert ( ty_classes [ 0 ] == .direct and ty_classes [ 1 ] == .direct );
1474+ } else {
14721475 assert (ty .abiSize (zcu ) == 16 );
14731476 // in this case we have an integer or float that must be lowered as 2 i64's.
14741477 try cg .emitWValue (value );
14751478 try cg .addMemArg (.i64_load , .{ .offset = value .offset (), .alignment = 8 });
14761479 try cg .emitWValue (value );
14771480 try cg .addMemArg (.i64_load , .{ .offset = value .offset () + 8 , .alignment = 8 });
14781481 },
1479- else = > return cg .lowerToStack (value ),
1482+ .indirect = > return cg .lowerToStack (value ),
14801483 }
14811484}
14821485
@@ -2142,23 +2145,16 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21422145 if (cg .return_value != .none ) {
21432146 try cg .store (cg .return_value , operand , ret_ty , 0 );
21442147 } else if (fn_info .cc == .wasm_mvp and ret_ty .hasRuntimeBitsIgnoreComptime (zcu )) {
2145- switch (ret_ty .zigTypeTag (zcu )) {
2146- // Aggregate types can be lowered as a singular value
2147- .@"struct" , .@"union" = > {
2148- const scalar_type = abi .scalarType (ret_ty , zcu );
2149- try cg .emitWValue (operand );
2150- const opcode = buildOpcode (.{
2151- .op = .load ,
2152- .width = @as (u8 , @intCast (scalar_type .abiSize (zcu ) * 8 )),
2153- .signedness = if (scalar_type .isSignedInt (zcu )) .signed else .unsigned ,
2154- .valtype1 = typeToValtype (scalar_type , zcu , cg .target ),
2155- });
2156- try cg .addMemArg (Mir .Inst .Tag .fromOpcode (opcode ), .{
2157- .offset = operand .offset (),
2158- .alignment = @intCast (scalar_type .abiAlignment (zcu ).toByteUnits ().? ),
2159- });
2148+ switch (abi .classifyType (ret_ty , zcu )) {
2149+ .direct = > | scalar_type | {
2150+ assert (! abi .lowerAsDoubleI64 (scalar_type , zcu ));
2151+ if (! isByRef (ret_ty , zcu , cg .target )) {
2152+ try cg .emitWValue (operand );
2153+ } else {
2154+ _ = try cg .load (operand , scalar_type , 0 );
2155+ }
21602156 },
2161- else = > try cg . emitWValue ( operand ) ,
2157+ .indirect = > unreachable ,
21622158 }
21632159 } else {
21642160 if (! ret_ty .hasRuntimeBitsIgnoreComptime (zcu ) and ret_ty .isError (zcu )) {
@@ -2284,14 +2280,24 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie
22842280 break :result_value .none ;
22852281 } else if (first_param_sret ) {
22862282 break :result_value sret ;
2287- // TODO: Make this less fragile and optimize
2288- } else if (zcu .typeToFunc (fn_ty ).? .cc == .wasm_mvp and ret_ty .zigTypeTag (zcu ) == .@"struct" or ret_ty .zigTypeTag (zcu ) == .@"union" ) {
2289- const result_local = try cg .allocLocal (ret_ty );
2290- try cg .addLocal (.local_set , result_local .local .value );
2291- const scalar_type = abi .scalarType (ret_ty , zcu );
2292- const result = try cg .allocStack (scalar_type );
2293- try cg .store (result , result_local , scalar_type , 0 );
2294- break :result_value result ;
2283+ } else if (zcu .typeToFunc (fn_ty ).? .cc == .wasm_mvp ) {
2284+ switch (abi .classifyType (ret_ty , zcu )) {
2285+ .direct = > | scalar_type | {
2286+ assert (! abi .lowerAsDoubleI64 (scalar_type , zcu ));
2287+ if (! isByRef (ret_ty , zcu , cg .target )) {
2288+ const result_local = try cg .allocLocal (ret_ty );
2289+ try cg .addLocal (.local_set , result_local .local .value );
2290+ break :result_value result_local ;
2291+ } else {
2292+ const result_local = try cg .allocLocal (ret_ty );
2293+ try cg .addLocal (.local_set , result_local .local .value );
2294+ const result = try cg .allocStack (ret_ty );
2295+ try cg .store (result , result_local , scalar_type , 0 );
2296+ break :result_value result ;
2297+ }
2298+ },
2299+ .indirect = > unreachable ,
2300+ }
22952301 } else {
22962302 const result_local = try cg .allocLocal (ret_ty );
22972303 try cg .addLocal (.local_set , result_local .local .value );
@@ -2597,26 +2603,17 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25972603 const cc = zcu .typeToFunc (zcu .navValue (cg .owner_nav ).typeOf (zcu )).? .cc ;
25982604 const arg_ty = cg .typeOfIndex (inst );
25992605 if (cc == .wasm_mvp ) {
2600- const arg_classes = abi .classifyType (arg_ty , zcu );
2601- for (arg_classes ) | class | {
2602- if (class != .none ) {
2606+ switch (abi .classifyType (arg_ty , zcu )) {
2607+ .direct = > | scalar_ty | if (! abi .lowerAsDoubleI64 (scalar_ty , zcu )) {
26032608 cg .arg_index += 1 ;
2604- }
2605- }
2606-
2607- // When we have an argument that's passed using more than a single parameter,
2608- // we combine them into a single stack value
2609- if (arg_classes [0 ] == .direct and arg_classes [1 ] == .direct ) {
2610- if (arg_ty .zigTypeTag (zcu ) != .int and arg_ty .zigTypeTag (zcu ) != .float ) {
2611- return cg .fail (
2612- "TODO: Implement C-ABI argument for type '{}'" ,
2613- .{arg_ty .fmt (pt )},
2614- );
2615- }
2616- const result = try cg .allocStack (arg_ty );
2617- try cg .store (result , arg , Type .u64 , 0 );
2618- try cg .store (result , cg .args [arg_index + 1 ], Type .u64 , 8 );
2619- return cg .finishAir (inst , result , &.{});
2609+ } else {
2610+ cg .arg_index += 2 ;
2611+ const result = try cg .allocStack (arg_ty );
2612+ try cg .store (result , arg , Type .u64 , 0 );
2613+ try cg .store (result , cg .args [arg_index + 1 ], Type .u64 , 8 );
2614+ return cg .finishAir (inst , result , &.{});
2615+ },
2616+ .indirect = > cg .arg_index += 1 ,
26202617 }
26212618 } else {
26222619 cg .arg_index += 1 ;
0 commit comments