| ... | @@ -921,6 +921,40 @@ pub const Object = struct { | ... | @@ -921,6 +921,40 @@ pub const Object = struct { |
| 921 | }; | 921 | }; |
| 922 | try args.append(loaded); | 922 | try args.append(loaded); |
| 923 | }, | 923 | }, |
| | 924 | .multiple_llvm_float => { |
| | 925 | const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len]; |
| | 926 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| | 927 | const param_llvm_ty = try dg.lowerType(param_ty); |
| | 928 | const param_alignment = param_ty.abiAlignment(target); |
| | 929 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); |
| | 930 | arg_ptr.setAlignment(param_alignment); |
| | 931 | var field_types_buf: [8]*const llvm.Type = undefined; |
| | 932 | const field_types = field_types_buf[0..llvm_floats.len]; |
| | 933 | for (llvm_floats) |float_bits, i| { |
| | 934 | switch (float_bits) { |
| | 935 | 64 => field_types[i] = dg.context.doubleType(), |
| | 936 | 80 => field_types[i] = dg.context.x86FP80Type(), |
| | 937 | else => {}, |
| | 938 | } |
| | 939 | } |
| | 940 | const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); |
| | 941 | const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); |
| | 942 | for (llvm_floats) |_, i_usize| { |
| | 943 | const i = @intCast(c_uint, i_usize); |
| | 944 | const param = llvm_func.getParam(i); |
| | 945 | const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); |
| | 946 | const store_inst = builder.buildStore(param, field_ptr); |
| | 947 | store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); |
| | 948 | } |
| | 949 | |
| | 950 | const is_by_ref = isByRef(param_ty); |
| | 951 | const loaded = if (is_by_ref) arg_ptr else l: { |
| | 952 | const load_inst = builder.buildLoad(arg_ptr, ""); |
| | 953 | load_inst.setAlignment(param_alignment); |
| | 954 | break :l load_inst; |
| | 955 | }; |
| | 956 | try args.append(loaded); |
| | 957 | }, |
| 924 | .as_u16 => { | 958 | .as_u16 => { |
| 925 | const param = llvm_func.getParam(llvm_arg_i); | 959 | const param = llvm_func.getParam(llvm_arg_i); |
| 926 | llvm_arg_i += 1; | 960 | llvm_arg_i += 1; |
| ... | @@ -2341,6 +2375,14 @@ pub const DeclGen = struct { | ... | @@ -2341,6 +2375,14 @@ pub const DeclGen = struct { |
| 2341 | dg.addFnAttr(llvm_fn, "noreturn"); | 2375 | dg.addFnAttr(llvm_fn, "noreturn"); |
| 2342 | } | 2376 | } |
| 2343 | | 2377 | |
| | 2378 | var llvm_arg_i = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing); |
| | 2379 | var it = iterateParamTypes(dg, fn_info); |
| | 2380 | while (it.next()) |_| : (llvm_arg_i += 1) { |
| | 2381 | if (!it.byval_attr) continue; |
| | 2382 | const param = llvm_fn.getParam(llvm_arg_i); |
| | 2383 | llvm_fn.addByValAttr(llvm_arg_i, param.typeOf().getElementType()); |
| | 2384 | } |
| | 2385 | |
| 2344 | return llvm_fn; | 2386 | return llvm_fn; |
| 2345 | } | 2387 | } |
| 2346 | | 2388 | |
| ... | @@ -2894,6 +2936,18 @@ pub const DeclGen = struct { | ... | @@ -2894,6 +2936,18 @@ pub const DeclGen = struct { |
| 2894 | llvm_params.appendAssumeCapacity(big_int_ty); | 2936 | llvm_params.appendAssumeCapacity(big_int_ty); |
| 2895 | } | 2937 | } |
| 2896 | }, | 2938 | }, |
| | 2939 | .multiple_llvm_float => { |
| | 2940 | const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len]; |
| | 2941 | try llvm_params.ensureUnusedCapacity(it.llvm_types_len); |
| | 2942 | for (llvm_ints) |float_bits| { |
| | 2943 | const float_ty = switch (float_bits) { |
| | 2944 | 64 => dg.context.doubleType(), |
| | 2945 | 80 => dg.context.x86FP80Type(), |
| | 2946 | else => unreachable, |
| | 2947 | }; |
| | 2948 | llvm_params.appendAssumeCapacity(float_ty); |
| | 2949 | } |
| | 2950 | }, |
| 2897 | .as_u16 => { | 2951 | .as_u16 => { |
| 2898 | try llvm_params.append(dg.context.intType(16)); | 2952 | try llvm_params.append(dg.context.intType(16)); |
| 2899 | }, | 2953 | }, |
| ... | @@ -4402,6 +4456,39 @@ pub const FuncGen = struct { | ... | @@ -4402,6 +4456,39 @@ pub const FuncGen = struct { |
| 4402 | llvm_args.appendAssumeCapacity(load_inst); | 4456 | llvm_args.appendAssumeCapacity(load_inst); |
| 4403 | } | 4457 | } |
| 4404 | }, | 4458 | }, |
| | 4459 | .multiple_llvm_float => { |
| | 4460 | const arg = args[it.zig_index - 1]; |
| | 4461 | const param_ty = self.air.typeOf(arg); |
| | 4462 | const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len]; |
| | 4463 | const llvm_arg = try self.resolveInst(arg); |
| | 4464 | const is_by_ref = isByRef(param_ty); |
| | 4465 | const arg_ptr = if (is_by_ref) llvm_arg else p: { |
| | 4466 | const p = self.buildAlloca(llvm_arg.typeOf()); |
| | 4467 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| | 4468 | store_inst.setAlignment(param_ty.abiAlignment(target)); |
| | 4469 | break :p p; |
| | 4470 | }; |
| | 4471 | |
| | 4472 | var field_types_buf: [8]*const llvm.Type = undefined; |
| | 4473 | const field_types = field_types_buf[0..llvm_floats.len]; |
| | 4474 | for (llvm_floats) |float_bits, i| { |
| | 4475 | switch (float_bits) { |
| | 4476 | 64 => field_types[i] = self.dg.context.doubleType(), |
| | 4477 | 80 => field_types[i] = self.dg.context.x86FP80Type(), |
| | 4478 | else => {}, |
| | 4479 | } |
| | 4480 | } |
| | 4481 | const ints_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); |
| | 4482 | const casted_ptr = self.builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); |
| | 4483 | try llvm_args.ensureUnusedCapacity(it.llvm_types_len); |
| | 4484 | for (llvm_floats) |_, i_usize| { |
| | 4485 | const i = @intCast(c_uint, i_usize); |
| | 4486 | const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); |
| | 4487 | const load_inst = self.builder.buildLoad(field_ptr, ""); |
| | 4488 | load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); |
| | 4489 | llvm_args.appendAssumeCapacity(load_inst); |
| | 4490 | } |
| | 4491 | }, |
| 4405 | .as_u16 => { | 4492 | .as_u16 => { |
| 4406 | const arg = args[it.zig_index - 1]; | 4493 | const arg = args[it.zig_index - 1]; |
| 4407 | const llvm_arg = try self.resolveInst(arg); | 4494 | const llvm_arg = try self.resolveInst(arg); |
| ... | @@ -9367,16 +9454,20 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. | ... | @@ -9367,16 +9454,20 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. |
| 9367 | llvm_types_index += 1; | 9454 | llvm_types_index += 1; |
| 9368 | }, | 9455 | }, |
| 9369 | .sse => { | 9456 | .sse => { |
| 9370 | @panic("TODO"); | 9457 | llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); |
| | 9458 | llvm_types_index += 1; |
| 9371 | }, | 9459 | }, |
| 9372 | .sseup => { | 9460 | .sseup => { |
| 9373 | @panic("TODO"); | 9461 | llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); |
| | 9462 | llvm_types_index += 1; |
| 9374 | }, | 9463 | }, |
| 9375 | .x87 => { | 9464 | .x87 => { |
| 9376 | @panic("TODO"); | 9465 | llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); |
| | 9466 | llvm_types_index += 1; |
| 9377 | }, | 9467 | }, |
| 9378 | .x87up => { | 9468 | .x87up => { |
| 9379 | @panic("TODO"); | 9469 | llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); |
| | 9470 | llvm_types_index += 1; |
| 9380 | }, | 9471 | }, |
| 9381 | .complex_x87 => { | 9472 | .complex_x87 => { |
| 9382 | @panic("TODO"); | 9473 | @panic("TODO"); |
| ... | @@ -9422,6 +9513,7 @@ const ParamTypeIterator = struct { | ... | @@ -9422,6 +9513,7 @@ const ParamTypeIterator = struct { |
| 9422 | target: std.Target, | 9513 | target: std.Target, |
| 9423 | llvm_types_len: u32, | 9514 | llvm_types_len: u32, |
| 9424 | llvm_types_buffer: [8]u16, | 9515 | llvm_types_buffer: [8]u16, |
| | 9516 | byval_attr: bool, |
| 9425 | | 9517 | |
| 9426 | const Lowering = enum { | 9518 | const Lowering = enum { |
| 9427 | no_bits, | 9519 | no_bits, |
| ... | @@ -9429,6 +9521,7 @@ const ParamTypeIterator = struct { | ... | @@ -9429,6 +9521,7 @@ const ParamTypeIterator = struct { |
| 9429 | byref, | 9521 | byref, |
| 9430 | abi_sized_int, | 9522 | abi_sized_int, |
| 9431 | multiple_llvm_ints, | 9523 | multiple_llvm_ints, |
| | 9524 | multiple_llvm_float, |
| 9432 | slice, | 9525 | slice, |
| 9433 | as_u16, | 9526 | as_u16, |
| 9434 | }; | 9527 | }; |
| ... | @@ -9436,6 +9529,7 @@ const ParamTypeIterator = struct { | ... | @@ -9436,6 +9529,7 @@ const ParamTypeIterator = struct { |
| 9436 | pub fn next(it: *ParamTypeIterator) ?Lowering { | 9529 | pub fn next(it: *ParamTypeIterator) ?Lowering { |
| 9437 | if (it.zig_index >= it.fn_info.param_types.len) return null; | 9530 | if (it.zig_index >= it.fn_info.param_types.len) return null; |
| 9438 | const ty = it.fn_info.param_types[it.zig_index]; | 9531 | const ty = it.fn_info.param_types[it.zig_index]; |
| | 9532 | it.byval_attr = false; |
| 9439 | return nextInner(it, ty); | 9533 | return nextInner(it, ty); |
| 9440 | } | 9534 | } |
| 9441 | | 9535 | |
| ... | @@ -9521,6 +9615,7 @@ const ParamTypeIterator = struct { | ... | @@ -9521,6 +9615,7 @@ const ParamTypeIterator = struct { |
| 9521 | .memory => { | 9615 | .memory => { |
| 9522 | it.zig_index += 1; | 9616 | it.zig_index += 1; |
| 9523 | it.llvm_index += 1; | 9617 | it.llvm_index += 1; |
| | 9618 | it.byval_attr = true; |
| 9524 | return .byref; | 9619 | return .byref; |
| 9525 | }, | 9620 | }, |
| 9526 | .sse => { | 9621 | .sse => { |
| ... | @@ -9540,6 +9635,7 @@ const ParamTypeIterator = struct { | ... | @@ -9540,6 +9635,7 @@ const ParamTypeIterator = struct { |
| 9540 | if (classes[0] == .memory) { | 9635 | if (classes[0] == .memory) { |
| 9541 | it.zig_index += 1; | 9636 | it.zig_index += 1; |
| 9542 | it.llvm_index += 1; | 9637 | it.llvm_index += 1; |
| | 9638 | it.byval_attr = true; |
| 9543 | return .byref; | 9639 | return .byref; |
| 9544 | } | 9640 | } |
| 9545 | var llvm_types_buffer: [8]u16 = undefined; | 9641 | var llvm_types_buffer: [8]u16 = undefined; |
| ... | @@ -9551,16 +9647,20 @@ const ParamTypeIterator = struct { | ... | @@ -9551,16 +9647,20 @@ const ParamTypeIterator = struct { |
| 9551 | llvm_types_index += 1; | 9647 | llvm_types_index += 1; |
| 9552 | }, | 9648 | }, |
| 9553 | .sse => { | 9649 | .sse => { |
| 9554 | @panic("TODO"); | 9650 | llvm_types_buffer[llvm_types_index] = 64; |
| | 9651 | llvm_types_index += 1; |
| 9555 | }, | 9652 | }, |
| 9556 | .sseup => { | 9653 | .sseup => { |
| 9557 | @panic("TODO"); | 9654 | llvm_types_buffer[llvm_types_index] = 64; |
| | 9655 | llvm_types_index += 1; |
| 9558 | }, | 9656 | }, |
| 9559 | .x87 => { | 9657 | .x87 => { |
| 9560 | @panic("TODO"); | 9658 | llvm_types_buffer[llvm_types_index] = 80; |
| | 9659 | llvm_types_index += 1; |
| 9561 | }, | 9660 | }, |
| 9562 | .x87up => { | 9661 | .x87up => { |
| 9563 | @panic("TODO"); | 9662 | llvm_types_buffer[llvm_types_index] = 80; |
| | 9663 | llvm_types_index += 1; |
| 9564 | }, | 9664 | }, |
| 9565 | .complex_x87 => { | 9665 | .complex_x87 => { |
| 9566 | @panic("TODO"); | 9666 | @panic("TODO"); |
| ... | @@ -9574,11 +9674,16 @@ const ParamTypeIterator = struct { | ... | @@ -9574,11 +9674,16 @@ const ParamTypeIterator = struct { |
| 9574 | it.llvm_index += 1; | 9674 | it.llvm_index += 1; |
| 9575 | return .abi_sized_int; | 9675 | return .abi_sized_int; |
| 9576 | } | 9676 | } |
| | 9677 | if (classes[0] == .sse and classes[1] == .none) { |
| | 9678 | it.zig_index += 1; |
| | 9679 | it.llvm_index += 1; |
| | 9680 | return .byval; |
| | 9681 | } |
| 9577 | it.llvm_types_buffer = llvm_types_buffer; | 9682 | it.llvm_types_buffer = llvm_types_buffer; |
| 9578 | it.llvm_types_len = llvm_types_index; | 9683 | it.llvm_types_len = llvm_types_index; |
| 9579 | it.llvm_index += llvm_types_index; | 9684 | it.llvm_index += llvm_types_index; |
| 9580 | it.zig_index += 1; | 9685 | it.zig_index += 1; |
| 9581 | return .multiple_llvm_ints; | 9686 | return if (classes[0] == .integer) .multiple_llvm_ints else .multiple_llvm_float; |
| 9582 | }, | 9687 | }, |
| 9583 | }, | 9688 | }, |
| 9584 | .wasm32 => { | 9689 | .wasm32 => { |
| ... | @@ -9619,6 +9724,7 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp | ... | @@ -9619,6 +9724,7 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp |
| 9619 | .target = dg.module.getTarget(), | 9724 | .target = dg.module.getTarget(), |
| 9620 | .llvm_types_buffer = undefined, | 9725 | .llvm_types_buffer = undefined, |
| 9621 | .llvm_types_len = 0, | 9726 | .llvm_types_len = 0, |
| | 9727 | .byval_attr = false, |
| 9622 | }; | 9728 | }; |
| 9623 | } | 9729 | } |
| 9624 | | 9730 | |