| ... | ... | @@ -921,6 +921,40 @@ pub const Object = struct { |
| 921 | 921 | }; |
| 922 | 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 | 958 | .as_u16 => { |
| 925 | 959 | const param = llvm_func.getParam(llvm_arg_i); |
| 926 | 960 | llvm_arg_i += 1; |
| ... | ... | @@ -2341,6 +2375,14 @@ pub const DeclGen = struct { |
| 2341 | 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 | 2386 | return llvm_fn; |
| 2345 | 2387 | } |
| 2346 | 2388 | |
| ... | ... | @@ -2894,6 +2936,18 @@ pub const DeclGen = struct { |
| 2894 | 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 | 2951 | .as_u16 => { |
| 2898 | 2952 | try llvm_params.append(dg.context.intType(16)); |
| 2899 | 2953 | }, |
| ... | ... | @@ -4402,6 +4456,39 @@ pub const FuncGen = struct { |
| 4402 | 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 | 4492 | .as_u16 => { |
| 4406 | 4493 | const arg = args[it.zig_index - 1]; |
| 4407 | 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 | 9454 | llvm_types_index += 1; |
| 9368 | 9455 | }, |
| 9369 | 9456 | .sse => { |
| 9370 | | @panic("TODO"); |
| 9457 | llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); |
| 9458 | llvm_types_index += 1; |
| 9371 | 9459 | }, |
| 9372 | 9460 | .sseup => { |
| 9373 | | @panic("TODO"); |
| 9461 | llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); |
| 9462 | llvm_types_index += 1; |
| 9374 | 9463 | }, |
| 9375 | 9464 | .x87 => { |
| 9376 | | @panic("TODO"); |
| 9465 | llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); |
| 9466 | llvm_types_index += 1; |
| 9377 | 9467 | }, |
| 9378 | 9468 | .x87up => { |
| 9379 | | @panic("TODO"); |
| 9469 | llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); |
| 9470 | llvm_types_index += 1; |
| 9380 | 9471 | }, |
| 9381 | 9472 | .complex_x87 => { |
| 9382 | 9473 | @panic("TODO"); |
| ... | ... | @@ -9422,6 +9513,7 @@ const ParamTypeIterator = struct { |
| 9422 | 9513 | target: std.Target, |
| 9423 | 9514 | llvm_types_len: u32, |
| 9424 | 9515 | llvm_types_buffer: [8]u16, |
| 9516 | byval_attr: bool, |
| 9425 | 9517 | |
| 9426 | 9518 | const Lowering = enum { |
| 9427 | 9519 | no_bits, |
| ... | ... | @@ -9429,6 +9521,7 @@ const ParamTypeIterator = struct { |
| 9429 | 9521 | byref, |
| 9430 | 9522 | abi_sized_int, |
| 9431 | 9523 | multiple_llvm_ints, |
| 9524 | multiple_llvm_float, |
| 9432 | 9525 | slice, |
| 9433 | 9526 | as_u16, |
| 9434 | 9527 | }; |
| ... | ... | @@ -9436,6 +9529,7 @@ const ParamTypeIterator = struct { |
| 9436 | 9529 | pub fn next(it: *ParamTypeIterator) ?Lowering { |
| 9437 | 9530 | if (it.zig_index >= it.fn_info.param_types.len) return null; |
| 9438 | 9531 | const ty = it.fn_info.param_types[it.zig_index]; |
| 9532 | it.byval_attr = false; |
| 9439 | 9533 | return nextInner(it, ty); |
| 9440 | 9534 | } |
| 9441 | 9535 | |
| ... | ... | @@ -9521,6 +9615,7 @@ const ParamTypeIterator = struct { |
| 9521 | 9615 | .memory => { |
| 9522 | 9616 | it.zig_index += 1; |
| 9523 | 9617 | it.llvm_index += 1; |
| 9618 | it.byval_attr = true; |
| 9524 | 9619 | return .byref; |
| 9525 | 9620 | }, |
| 9526 | 9621 | .sse => { |
| ... | ... | @@ -9540,6 +9635,7 @@ const ParamTypeIterator = struct { |
| 9540 | 9635 | if (classes[0] == .memory) { |
| 9541 | 9636 | it.zig_index += 1; |
| 9542 | 9637 | it.llvm_index += 1; |
| 9638 | it.byval_attr = true; |
| 9543 | 9639 | return .byref; |
| 9544 | 9640 | } |
| 9545 | 9641 | var llvm_types_buffer: [8]u16 = undefined; |
| ... | ... | @@ -9551,16 +9647,20 @@ const ParamTypeIterator = struct { |
| 9551 | 9647 | llvm_types_index += 1; |
| 9552 | 9648 | }, |
| 9553 | 9649 | .sse => { |
| 9554 | | @panic("TODO"); |
| 9650 | llvm_types_buffer[llvm_types_index] = 64; |
| 9651 | llvm_types_index += 1; |
| 9555 | 9652 | }, |
| 9556 | 9653 | .sseup => { |
| 9557 | | @panic("TODO"); |
| 9654 | llvm_types_buffer[llvm_types_index] = 64; |
| 9655 | llvm_types_index += 1; |
| 9558 | 9656 | }, |
| 9559 | 9657 | .x87 => { |
| 9560 | | @panic("TODO"); |
| 9658 | llvm_types_buffer[llvm_types_index] = 80; |
| 9659 | llvm_types_index += 1; |
| 9561 | 9660 | }, |
| 9562 | 9661 | .x87up => { |
| 9563 | | @panic("TODO"); |
| 9662 | llvm_types_buffer[llvm_types_index] = 80; |
| 9663 | llvm_types_index += 1; |
| 9564 | 9664 | }, |
| 9565 | 9665 | .complex_x87 => { |
| 9566 | 9666 | @panic("TODO"); |
| ... | ... | @@ -9574,11 +9674,16 @@ const ParamTypeIterator = struct { |
| 9574 | 9674 | it.llvm_index += 1; |
| 9575 | 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 | 9682 | it.llvm_types_buffer = llvm_types_buffer; |
| 9578 | 9683 | it.llvm_types_len = llvm_types_index; |
| 9579 | 9684 | it.llvm_index += llvm_types_index; |
| 9580 | 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 | 9689 | .wasm32 => { |
| ... | ... | @@ -9619,6 +9724,7 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp |
| 9619 | 9724 | .target = dg.module.getTarget(), |
| 9620 | 9725 | .llvm_types_buffer = undefined, |
| 9621 | 9726 | .llvm_types_len = 0, |
| 9727 | .byval_attr = false, |
| 9622 | 9728 | }; |
| 9623 | 9729 | } |
| 9624 | 9730 | |