| ... | @@ -841,7 +841,8 @@ pub const Object = struct { | ... | @@ -841,7 +841,8 @@ pub const Object = struct { |
| 841 | args.appendAssumeCapacity(param); | 841 | args.appendAssumeCapacity(param); |
| 842 | } else { | 842 | } else { |
| 843 | const alignment = param_ty.abiAlignment(target); | 843 | const alignment = param_ty.abiAlignment(target); |
| 844 | const load_inst = builder.buildLoad(param, ""); | 844 | const param_llvm_ty = try dg.lowerType(param_ty); |
| | 845 | const load_inst = builder.buildLoad(param_llvm_ty, param, ""); |
| 845 | load_inst.setAlignment(alignment); | 846 | load_inst.setAlignment(alignment); |
| 846 | args.appendAssumeCapacity(load_inst); | 847 | args.appendAssumeCapacity(load_inst); |
| 847 | } | 848 | } |
| ... | @@ -870,7 +871,7 @@ pub const Object = struct { | ... | @@ -870,7 +871,7 @@ pub const Object = struct { |
| 870 | if (isByRef(param_ty)) { | 871 | if (isByRef(param_ty)) { |
| 871 | args.appendAssumeCapacity(arg_ptr); | 872 | args.appendAssumeCapacity(arg_ptr); |
| 872 | } else { | 873 | } else { |
| 873 | const load_inst = builder.buildLoad(arg_ptr, ""); | 874 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); |
| 874 | load_inst.setAlignment(alignment); | 875 | load_inst.setAlignment(alignment); |
| 875 | args.appendAssumeCapacity(load_inst); | 876 | args.appendAssumeCapacity(load_inst); |
| 876 | } | 877 | } |
| ... | @@ -921,14 +922,14 @@ pub const Object = struct { | ... | @@ -921,14 +922,14 @@ pub const Object = struct { |
| 921 | for (llvm_ints) |_, i_usize| { | 922 | for (llvm_ints) |_, i_usize| { |
| 922 | const i = @intCast(c_uint, i_usize); | 923 | const i = @intCast(c_uint, i_usize); |
| 923 | const param = llvm_func.getParam(i); | 924 | const param = llvm_func.getParam(i); |
| 924 | const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); | 925 | const field_ptr = builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); |
| 925 | const store_inst = builder.buildStore(param, field_ptr); | 926 | const store_inst = builder.buildStore(param, field_ptr); |
| 926 | store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); | 927 | store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); |
| 927 | } | 928 | } |
| 928 | | 929 | |
| 929 | const is_by_ref = isByRef(param_ty); | 930 | const is_by_ref = isByRef(param_ty); |
| 930 | const loaded = if (is_by_ref) arg_ptr else l: { | 931 | const loaded = if (is_by_ref) arg_ptr else l: { |
| 931 | const load_inst = builder.buildLoad(arg_ptr, ""); | 932 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); |
| 932 | load_inst.setAlignment(param_alignment); | 933 | load_inst.setAlignment(param_alignment); |
| 933 | break :l load_inst; | 934 | break :l load_inst; |
| 934 | }; | 935 | }; |
| ... | @@ -3663,7 +3664,8 @@ pub const DeclGen = struct { | ... | @@ -3663,7 +3664,8 @@ pub const DeclGen = struct { |
| 3663 | llvm_u32.constInt(0, .False), | 3664 | llvm_u32.constInt(0, .False), |
| 3664 | llvm_u32.constInt(llvm_pl_index, .False), | 3665 | llvm_u32.constInt(llvm_pl_index, .False), |
| 3665 | }; | 3666 | }; |
| 3666 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); | 3667 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| | 3668 | break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3667 | }, | 3669 | }, |
| 3668 | .Struct => { | 3670 | .Struct => { |
| 3669 | const field_ty = parent_ty.structFieldType(field_index); | 3671 | const field_ty = parent_ty.structFieldType(field_index); |
| ... | @@ -3693,7 +3695,8 @@ pub const DeclGen = struct { | ... | @@ -3693,7 +3695,8 @@ pub const DeclGen = struct { |
| 3693 | llvm_u32.constInt(0, .False), | 3695 | llvm_u32.constInt(0, .False), |
| 3694 | llvm_u32.constInt(llvm_field_index, .False), | 3696 | llvm_u32.constInt(llvm_field_index, .False), |
| 3695 | }; | 3697 | }; |
| 3696 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); | 3698 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| | 3699 | break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3697 | }, | 3700 | }, |
| 3698 | else => unreachable, | 3701 | else => unreachable, |
| 3699 | } | 3702 | } |
| ... | @@ -3707,7 +3710,8 @@ pub const DeclGen = struct { | ... | @@ -3707,7 +3710,8 @@ pub const DeclGen = struct { |
| 3707 | const indices: [1]*const llvm.Value = .{ | 3710 | const indices: [1]*const llvm.Value = .{ |
| 3708 | llvm_usize.constInt(elem_ptr.index, .False), | 3711 | llvm_usize.constInt(elem_ptr.index, .False), |
| 3709 | }; | 3712 | }; |
| 3710 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); | 3713 | const elem_llvm_ty = try dg.lowerType(elem_ptr.elem_ty); |
| | 3714 | break :blk elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3711 | }, | 3715 | }, |
| 3712 | .opt_payload_ptr => blk: { | 3716 | .opt_payload_ptr => blk: { |
| 3713 | const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; | 3717 | const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| ... | @@ -3730,7 +3734,8 @@ pub const DeclGen = struct { | ... | @@ -3730,7 +3734,8 @@ pub const DeclGen = struct { |
| 3730 | llvm_u32.constInt(0, .False), | 3734 | llvm_u32.constInt(0, .False), |
| 3731 | llvm_u32.constInt(0, .False), | 3735 | llvm_u32.constInt(0, .False), |
| 3732 | }; | 3736 | }; |
| 3733 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); | 3737 | const opt_llvm_ty = try dg.lowerType(opt_payload_ptr.container_ty); |
| | 3738 | break :blk opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3734 | }, | 3739 | }, |
| 3735 | .eu_payload_ptr => blk: { | 3740 | .eu_payload_ptr => blk: { |
| 3736 | const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; | 3741 | const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; |
| ... | @@ -3751,7 +3756,8 @@ pub const DeclGen = struct { | ... | @@ -3751,7 +3756,8 @@ pub const DeclGen = struct { |
| 3751 | llvm_u32.constInt(0, .False), | 3756 | llvm_u32.constInt(0, .False), |
| 3752 | llvm_u32.constInt(payload_offset, .False), | 3757 | llvm_u32.constInt(payload_offset, .False), |
| 3753 | }; | 3758 | }; |
| 3754 | break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); | 3759 | const eu_llvm_ty = try dg.lowerType(eu_payload_ptr.container_ty); |
| | 3760 | break :blk eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3755 | }, | 3761 | }, |
| 3756 | else => unreachable, | 3762 | else => unreachable, |
| 3757 | }; | 3763 | }; |
| ... | @@ -4303,9 +4309,10 @@ pub const FuncGen = struct { | ... | @@ -4303,9 +4309,10 @@ pub const FuncGen = struct { |
| 4303 | const arg = args[it.zig_index - 1]; | 4309 | const arg = args[it.zig_index - 1]; |
| 4304 | const param_ty = self.air.typeOf(arg); | 4310 | const param_ty = self.air.typeOf(arg); |
| 4305 | const llvm_arg = try self.resolveInst(arg); | 4311 | const llvm_arg = try self.resolveInst(arg); |
| | 4312 | const llvm_param_ty = try self.dg.lowerType(param_ty); |
| 4306 | if (isByRef(param_ty)) { | 4313 | if (isByRef(param_ty)) { |
| 4307 | const alignment = param_ty.abiAlignment(target); | 4314 | const alignment = param_ty.abiAlignment(target); |
| 4308 | const load_inst = self.builder.buildLoad(llvm_arg, ""); | 4315 | const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); |
| 4309 | load_inst.setAlignment(alignment); | 4316 | load_inst.setAlignment(alignment); |
| 4310 | try llvm_args.append(load_inst); | 4317 | try llvm_args.append(load_inst); |
| 4311 | } else { | 4318 | } else { |
| ... | @@ -4315,7 +4322,6 @@ pub const FuncGen = struct { | ... | @@ -4315,7 +4322,6 @@ pub const FuncGen = struct { |
| 4315 | // which is always lowered to an LLVM type of `*i8`. | 4322 | // which is always lowered to an LLVM type of `*i8`. |
| 4316 | // 2. The argument is a global which does act as a pointer, however | 4323 | // 2. The argument is a global which does act as a pointer, however |
| 4317 | // a bitcast is needed in order for the LLVM types to match. | 4324 | // a bitcast is needed in order for the LLVM types to match. |
| 4318 | const llvm_param_ty = try self.dg.lowerType(param_ty); | | |
| 4319 | const casted_ptr = self.builder.buildBitCast(llvm_arg, llvm_param_ty, ""); | 4325 | const casted_ptr = self.builder.buildBitCast(llvm_arg, llvm_param_ty, ""); |
| 4320 | try llvm_args.append(casted_ptr); | 4326 | try llvm_args.append(casted_ptr); |
| 4321 | } else { | 4327 | } else { |
| ... | @@ -4350,7 +4356,7 @@ pub const FuncGen = struct { | ... | @@ -4350,7 +4356,7 @@ pub const FuncGen = struct { |
| 4350 | if (isByRef(param_ty)) { | 4356 | if (isByRef(param_ty)) { |
| 4351 | const alignment = param_ty.abiAlignment(target); | 4357 | const alignment = param_ty.abiAlignment(target); |
| 4352 | const casted_ptr = self.builder.buildBitCast(llvm_arg, int_ptr_llvm_ty, ""); | 4358 | const casted_ptr = self.builder.buildBitCast(llvm_arg, int_ptr_llvm_ty, ""); |
| 4353 | const load_inst = self.builder.buildLoad(casted_ptr, ""); | 4359 | const load_inst = self.builder.buildLoad(int_llvm_ty, casted_ptr, ""); |
| 4354 | load_inst.setAlignment(alignment); | 4360 | load_inst.setAlignment(alignment); |
| 4355 | try llvm_args.append(load_inst); | 4361 | try llvm_args.append(load_inst); |
| 4356 | } else { | 4362 | } else { |
| ... | @@ -4366,7 +4372,7 @@ pub const FuncGen = struct { | ... | @@ -4366,7 +4372,7 @@ pub const FuncGen = struct { |
| 4366 | const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); | 4372 | const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); |
| 4367 | const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); | 4373 | const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); |
| 4368 | store_inst.setAlignment(alignment); | 4374 | store_inst.setAlignment(alignment); |
| 4369 | const load_inst = self.builder.buildLoad(int_ptr, ""); | 4375 | const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); |
| 4370 | load_inst.setAlignment(alignment); | 4376 | load_inst.setAlignment(alignment); |
| 4371 | try llvm_args.append(load_inst); | 4377 | try llvm_args.append(load_inst); |
| 4372 | } | 4378 | } |
| ... | @@ -4403,8 +4409,8 @@ pub const FuncGen = struct { | ... | @@ -4403,8 +4409,8 @@ pub const FuncGen = struct { |
| 4403 | try llvm_args.ensureUnusedCapacity(it.llvm_types_len); | 4409 | try llvm_args.ensureUnusedCapacity(it.llvm_types_len); |
| 4404 | for (llvm_ints) |_, i_usize| { | 4410 | for (llvm_ints) |_, i_usize| { |
| 4405 | const i = @intCast(c_uint, i_usize); | 4411 | const i = @intCast(c_uint, i_usize); |
| 4406 | const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); | 4412 | const field_ptr = self.builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); |
| 4407 | const load_inst = self.builder.buildLoad(field_ptr, ""); | 4413 | const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); |
| 4408 | load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); | 4414 | load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); |
| 4409 | llvm_args.appendAssumeCapacity(load_inst); | 4415 | llvm_args.appendAssumeCapacity(load_inst); |
| 4410 | } | 4416 | } |
| ... | @@ -4418,6 +4424,7 @@ pub const FuncGen = struct { | ... | @@ -4418,6 +4424,7 @@ pub const FuncGen = struct { |
| 4418 | }; | 4424 | }; |
| 4419 | | 4425 | |
| 4420 | const call = self.builder.buildCall( | 4426 | const call = self.builder.buildCall( |
| | 4427 | try self.dg.lowerType(zig_fn_ty), |
| 4421 | llvm_fn, | 4428 | llvm_fn, |
| 4422 | llvm_args.items.ptr, | 4429 | llvm_args.items.ptr, |
| 4423 | @intCast(c_uint, llvm_args.items.len), | 4430 | @intCast(c_uint, llvm_args.items.len), |
| ... | @@ -4443,7 +4450,7 @@ pub const FuncGen = struct { | ... | @@ -4443,7 +4450,7 @@ pub const FuncGen = struct { |
| 4443 | return rp; | 4450 | return rp; |
| 4444 | } else { | 4451 | } else { |
| 4445 | // our by-ref status disagrees with sret so we must load. | 4452 | // our by-ref status disagrees with sret so we must load. |
| 4446 | const loaded = self.builder.buildLoad(rp, ""); | 4453 | const loaded = self.builder.buildLoad(llvm_ret_ty, rp, ""); |
| 4447 | loaded.setAlignment(return_type.abiAlignment(target)); | 4454 | loaded.setAlignment(return_type.abiAlignment(target)); |
| 4448 | return loaded; | 4455 | return loaded; |
| 4449 | } | 4456 | } |
| ... | @@ -4465,7 +4472,7 @@ pub const FuncGen = struct { | ... | @@ -4465,7 +4472,7 @@ pub const FuncGen = struct { |
| 4465 | if (isByRef(return_type)) { | 4472 | if (isByRef(return_type)) { |
| 4466 | return rp; | 4473 | return rp; |
| 4467 | } else { | 4474 | } else { |
| 4468 | const load_inst = self.builder.buildLoad(rp, ""); | 4475 | const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, ""); |
| 4469 | load_inst.setAlignment(alignment); | 4476 | load_inst.setAlignment(alignment); |
| 4470 | return load_inst; | 4477 | return load_inst; |
| 4471 | } | 4478 | } |
| ... | @@ -4523,7 +4530,7 @@ pub const FuncGen = struct { | ... | @@ -4523,7 +4530,7 @@ pub const FuncGen = struct { |
| 4523 | // operand is a pointer however self.ret_ptr is null so that means | 4530 | // operand is a pointer however self.ret_ptr is null so that means |
| 4524 | // we need to return a value. | 4531 | // we need to return a value. |
| 4525 | const casted_ptr = self.builder.buildBitCast(operand, ptr_abi_ty, ""); | 4532 | const casted_ptr = self.builder.buildBitCast(operand, ptr_abi_ty, ""); |
| 4526 | const load_inst = self.builder.buildLoad(casted_ptr, ""); | 4533 | const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); |
| 4527 | load_inst.setAlignment(alignment); | 4534 | load_inst.setAlignment(alignment); |
| 4528 | _ = self.builder.buildRet(load_inst); | 4535 | _ = self.builder.buildRet(load_inst); |
| 4529 | return null; | 4536 | return null; |
| ... | @@ -4540,7 +4547,7 @@ pub const FuncGen = struct { | ... | @@ -4540,7 +4547,7 @@ pub const FuncGen = struct { |
| 4540 | const store_inst = self.builder.buildStore(operand, rp); | 4547 | const store_inst = self.builder.buildStore(operand, rp); |
| 4541 | store_inst.setAlignment(alignment); | 4548 | store_inst.setAlignment(alignment); |
| 4542 | const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); | 4549 | const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); |
| 4543 | const load_inst = self.builder.buildLoad(casted_ptr, ""); | 4550 | const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); |
| 4544 | load_inst.setAlignment(alignment); | 4551 | load_inst.setAlignment(alignment); |
| 4545 | _ = self.builder.buildRet(load_inst); | 4552 | _ = self.builder.buildRet(load_inst); |
| 4546 | return null; | 4553 | return null; |
| ... | @@ -4575,7 +4582,7 @@ pub const FuncGen = struct { | ... | @@ -4575,7 +4582,7 @@ pub const FuncGen = struct { |
| 4575 | const ptr_abi_ty = abi_ret_ty.pointerType(0); | 4582 | const ptr_abi_ty = abi_ret_ty.pointerType(0); |
| 4576 | break :p self.builder.buildBitCast(ptr, ptr_abi_ty, ""); | 4583 | break :p self.builder.buildBitCast(ptr, ptr_abi_ty, ""); |
| 4577 | }; | 4584 | }; |
| 4578 | const loaded = self.builder.buildLoad(casted_ptr, ""); | 4585 | const loaded = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); |
| 4579 | loaded.setAlignment(ret_ty.abiAlignment(target)); | 4586 | loaded.setAlignment(ret_ty.abiAlignment(target)); |
| 4580 | _ = self.builder.buildRet(loaded); | 4587 | _ = self.builder.buildRet(loaded); |
| 4581 | return null; | 4588 | return null; |
| ... | @@ -4615,7 +4622,7 @@ pub const FuncGen = struct { | ... | @@ -4615,7 +4622,7 @@ pub const FuncGen = struct { |
| 4615 | const operand = try self.resolveInst(un_op); | 4622 | const operand = try self.resolveInst(un_op); |
| 4616 | const llvm_fn = try self.getCmpLtErrorsLenFunction(); | 4623 | const llvm_fn = try self.getCmpLtErrorsLenFunction(); |
| 4617 | const args: [1]*const llvm.Value = .{operand}; | 4624 | const args: [1]*const llvm.Value = .{operand}; |
| 4618 | return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); | 4625 | return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 4619 | } | 4626 | } |
| 4620 | | 4627 | |
| 4621 | fn cmp( | 4628 | fn cmp( |
| ... | @@ -4642,8 +4649,9 @@ pub const FuncGen = struct { | ... | @@ -4642,8 +4649,9 @@ pub const FuncGen = struct { |
| 4642 | // We need to emit instructions to check for equality/inequality | 4649 | // We need to emit instructions to check for equality/inequality |
| 4643 | // of optionals that are not pointers. | 4650 | // of optionals that are not pointers. |
| 4644 | const is_by_ref = isByRef(scalar_ty); | 4651 | const is_by_ref = isByRef(scalar_ty); |
| 4645 | const lhs_non_null = self.optIsNonNull(lhs, is_by_ref); | 4652 | const opt_llvm_ty = try self.dg.lowerType(scalar_ty); |
| 4646 | const rhs_non_null = self.optIsNonNull(rhs, is_by_ref); | 4653 | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); |
| | 4654 | const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); |
| 4647 | const llvm_i2 = self.context.intType(2); | 4655 | const llvm_i2 = self.context.intType(2); |
| 4648 | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); | 4656 | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); |
| 4649 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); | 4657 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); |
| ... | @@ -4666,8 +4674,8 @@ pub const FuncGen = struct { | ... | @@ -4666,8 +4674,8 @@ pub const FuncGen = struct { |
| 4666 | _ = self.builder.buildBr(end_block); | 4674 | _ = self.builder.buildBr(end_block); |
| 4667 | | 4675 | |
| 4668 | self.builder.positionBuilderAtEnd(both_pl_block); | 4676 | self.builder.positionBuilderAtEnd(both_pl_block); |
| 4669 | const lhs_payload = self.optPayloadHandle(lhs, scalar_ty); | 4677 | const lhs_payload = self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); |
| 4670 | const rhs_payload = self.optPayloadHandle(rhs, scalar_ty); | 4678 | const rhs_payload = self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); |
| 4671 | const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); | 4679 | const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); |
| 4672 | _ = self.builder.buildBr(end_block); | 4680 | _ = self.builder.buildBr(end_block); |
| 4673 | const both_pl_block_end = self.builder.getInsertBlock(); | 4681 | const both_pl_block_end = self.builder.getInsertBlock(); |
| ... | @@ -4832,10 +4840,18 @@ pub const FuncGen = struct { | ... | @@ -4832,10 +4840,18 @@ pub const FuncGen = struct { |
| 4832 | return lowerTry(self, err_union_ptr, body, err_union_ty, true, result_ty); | 4840 | return lowerTry(self, err_union_ptr, body, err_union_ty, true, result_ty); |
| 4833 | } | 4841 | } |
| 4834 | | 4842 | |
| 4835 | fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value { | 4843 | fn lowerTry( |
| | 4844 | fg: *FuncGen, |
| | 4845 | err_union: *const llvm.Value, |
| | 4846 | body: []const Air.Inst.Index, |
| | 4847 | err_union_ty: Type, |
| | 4848 | operand_is_ptr: bool, |
| | 4849 | result_ty: Type, |
| | 4850 | ) !?*const llvm.Value { |
| 4836 | const payload_ty = err_union_ty.errorUnionPayload(); | 4851 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 4837 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); | 4852 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); |
| 4838 | const target = fg.dg.module.getTarget(); | 4853 | const target = fg.dg.module.getTarget(); |
| | 4854 | const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); |
| 4839 | | 4855 | |
| 4840 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { | 4856 | if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { |
| 4841 | const is_err = err: { | 4857 | const is_err = err: { |
| ... | @@ -4843,14 +4859,17 @@ pub const FuncGen = struct { | ... | @@ -4843,14 +4859,17 @@ pub const FuncGen = struct { |
| 4843 | const zero = err_set_ty.constNull(); | 4859 | const zero = err_set_ty.constNull(); |
| 4844 | if (!payload_has_bits) { | 4860 | if (!payload_has_bits) { |
| 4845 | // TODO add alignment to this load | 4861 | // TODO add alignment to this load |
| 4846 | const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; | 4862 | const loaded = if (operand_is_ptr) |
| | 4863 | fg.builder.buildLoad(err_set_ty, err_union, "") |
| | 4864 | else |
| | 4865 | err_union; |
| 4847 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | 4866 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4848 | } | 4867 | } |
| 4849 | const err_field_index = errUnionErrorOffset(payload_ty, target); | 4868 | const err_field_index = errUnionErrorOffset(payload_ty, target); |
| 4850 | if (operand_is_ptr or isByRef(err_union_ty)) { | 4869 | if (operand_is_ptr or isByRef(err_union_ty)) { |
| 4851 | const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); | 4870 | const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, ""); |
| 4852 | // TODO add alignment to this load | 4871 | // TODO add alignment to this load |
| 4853 | const loaded = fg.builder.buildLoad(err_field_ptr, ""); | 4872 | const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, ""); |
| 4854 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); | 4873 | break :err fg.builder.buildICmp(.NE, loaded, zero, ""); |
| 4855 | } | 4874 | } |
| 4856 | const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); | 4875 | const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); |
| ... | @@ -4876,13 +4895,13 @@ pub const FuncGen = struct { | ... | @@ -4876,13 +4895,13 @@ pub const FuncGen = struct { |
| 4876 | } | 4895 | } |
| 4877 | const offset = errUnionPayloadOffset(payload_ty, target); | 4896 | const offset = errUnionPayloadOffset(payload_ty, target); |
| 4878 | if (operand_is_ptr or isByRef(payload_ty)) { | 4897 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 4879 | return fg.builder.buildStructGEP(err_union, offset, ""); | 4898 | return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); |
| 4880 | } else if (isByRef(err_union_ty)) { | 4899 | } else if (isByRef(err_union_ty)) { |
| 4881 | const payload_ptr = fg.builder.buildStructGEP(err_union, offset, ""); | 4900 | const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); |
| 4882 | if (isByRef(payload_ty)) { | 4901 | if (isByRef(payload_ty)) { |
| 4883 | return payload_ptr; | 4902 | return payload_ptr; |
| 4884 | } | 4903 | } |
| 4885 | const load_inst = fg.builder.buildLoad(payload_ptr, ""); | 4904 | const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); |
| 4886 | load_inst.setAlignment(payload_ty.abiAlignment(target)); | 4905 | load_inst.setAlignment(payload_ty.abiAlignment(target)); |
| 4887 | return load_inst; | 4906 | return load_inst; |
| 4888 | } | 4907 | } |
| ... | @@ -4977,7 +4996,8 @@ pub const FuncGen = struct { | ... | @@ -4977,7 +4996,8 @@ pub const FuncGen = struct { |
| 4977 | const indices: [2]*const llvm.Value = .{ | 4996 | const indices: [2]*const llvm.Value = .{ |
| 4978 | llvm_usize.constNull(), llvm_usize.constNull(), | 4997 | llvm_usize.constNull(), llvm_usize.constNull(), |
| 4979 | }; | 4998 | }; |
| 4980 | const ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); | 4999 | const elem_llvm_ty = try self.dg.lowerType(array_ty.childType()); |
| | 5000 | const ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indices, indices.len, ""); |
| 4981 | const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); | 5001 | const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); |
| 4982 | return self.builder.buildInsertValue(partial, len, 1, ""); | 5002 | return self.builder.buildInsertValue(partial, len, 1, ""); |
| 4983 | } | 5003 | } |
| ... | @@ -5038,7 +5058,7 @@ pub const FuncGen = struct { | ... | @@ -5038,7 +5058,7 @@ pub const FuncGen = struct { |
| 5038 | const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); | 5058 | const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); |
| 5039 | const params = [1]*const llvm.Value{extended}; | 5059 | const params = [1]*const llvm.Value{extended}; |
| 5040 | | 5060 | |
| 5041 | return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, ""); | 5061 | return self.builder.buildCall(libc_fn.typeOf(), libc_fn, &params, params.len, .C, .Auto, ""); |
| 5042 | } | 5062 | } |
| 5043 | | 5063 | |
| 5044 | fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { | 5064 | fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { |
| ... | @@ -5093,7 +5113,7 @@ pub const FuncGen = struct { | ... | @@ -5093,7 +5113,7 @@ pub const FuncGen = struct { |
| 5093 | const libc_fn = self.getLibcFunction(fn_name, &param_types, libc_ret_ty); | 5113 | const libc_fn = self.getLibcFunction(fn_name, &param_types, libc_ret_ty); |
| 5094 | const params = [1]*const llvm.Value{operand}; | 5114 | const params = [1]*const llvm.Value{operand}; |
| 5095 | | 5115 | |
| 5096 | var result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, ""); | 5116 | var result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, &params, params.len, .C, .Auto, ""); |
| 5097 | | 5117 | |
| 5098 | if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); | 5118 | if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); |
| 5099 | if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); | 5119 | if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); |
| ... | @@ -5113,8 +5133,9 @@ pub const FuncGen = struct { | ... | @@ -5113,8 +5133,9 @@ pub const FuncGen = struct { |
| 5113 | | 5133 | |
| 5114 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5134 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5115 | const slice_ptr = try self.resolveInst(ty_op.operand); | 5135 | const slice_ptr = try self.resolveInst(ty_op.operand); |
| | 5136 | const slice_llvm_ty = try self.dg.lowerType(self.air.typeOf(ty_op.operand).childType()); |
| 5116 | | 5137 | |
| 5117 | return self.builder.buildStructGEP(slice_ptr, index, ""); | 5138 | return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); |
| 5118 | } | 5139 | } |
| 5119 | | 5140 | |
| 5120 | fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 5141 | fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -5124,7 +5145,10 @@ pub const FuncGen = struct { | ... | @@ -5124,7 +5145,10 @@ pub const FuncGen = struct { |
| 5124 | | 5145 | |
| 5125 | const slice = try self.resolveInst(bin_op.lhs); | 5146 | const slice = try self.resolveInst(bin_op.lhs); |
| 5126 | const index = try self.resolveInst(bin_op.rhs); | 5147 | const index = try self.resolveInst(bin_op.rhs); |
| 5127 | const ptr = self.sliceElemPtr(slice, index); | 5148 | const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); |
| | 5149 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); |
| | 5150 | const indices: [1]*const llvm.Value = .{index}; |
| | 5151 | const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5128 | return self.load(ptr, slice_ty); | 5152 | return self.load(ptr, slice_ty); |
| 5129 | } | 5153 | } |
| 5130 | | 5154 | |
| ... | @@ -5132,10 +5156,14 @@ pub const FuncGen = struct { | ... | @@ -5132,10 +5156,14 @@ pub const FuncGen = struct { |
| 5132 | if (self.liveness.isUnused(inst)) return null; | 5156 | if (self.liveness.isUnused(inst)) return null; |
| 5133 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5157 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5134 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 5158 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| | 5159 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 5135 | | 5160 | |
| 5136 | const slice = try self.resolveInst(bin_op.lhs); | 5161 | const slice = try self.resolveInst(bin_op.lhs); |
| 5137 | const index = try self.resolveInst(bin_op.rhs); | 5162 | const index = try self.resolveInst(bin_op.rhs); |
| 5138 | return self.sliceElemPtr(slice, index); | 5163 | const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); |
| | 5164 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); |
| | 5165 | const indices: [1]*const llvm.Value = .{index}; |
| | 5166 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5139 | } | 5167 | } |
| 5140 | | 5168 | |
| 5141 | fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 5169 | fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -5146,13 +5174,14 @@ pub const FuncGen = struct { | ... | @@ -5146,13 +5174,14 @@ pub const FuncGen = struct { |
| 5146 | const array_llvm_val = try self.resolveInst(bin_op.lhs); | 5174 | const array_llvm_val = try self.resolveInst(bin_op.lhs); |
| 5147 | const rhs = try self.resolveInst(bin_op.rhs); | 5175 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5148 | if (isByRef(array_ty)) { | 5176 | if (isByRef(array_ty)) { |
| 5149 | const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; | | |
| 5150 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_val, &indices, indices.len, ""); | | |
| 5151 | const elem_ty = array_ty.childType(); | 5177 | const elem_ty = array_ty.childType(); |
| | 5178 | const elem_llvm_ty = try self.dg.lowerType(elem_ty); |
| | 5179 | const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| | 5180 | const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, array_llvm_val, &indices, indices.len, ""); |
| 5152 | if (isByRef(elem_ty)) { | 5181 | if (isByRef(elem_ty)) { |
| 5153 | return elem_ptr; | 5182 | return elem_ptr; |
| 5154 | } else { | 5183 | } else { |
| 5155 | return self.builder.buildLoad(elem_ptr, ""); | 5184 | return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); |
| 5156 | } | 5185 | } |
| 5157 | } | 5186 | } |
| 5158 | | 5187 | |
| ... | @@ -5165,15 +5194,16 @@ pub const FuncGen = struct { | ... | @@ -5165,15 +5194,16 @@ pub const FuncGen = struct { |
| 5165 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 5194 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 5166 | if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; | 5195 | if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; |
| 5167 | | 5196 | |
| | 5197 | const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); |
| 5168 | const base_ptr = try self.resolveInst(bin_op.lhs); | 5198 | const base_ptr = try self.resolveInst(bin_op.lhs); |
| 5169 | const rhs = try self.resolveInst(bin_op.rhs); | 5199 | const rhs = try self.resolveInst(bin_op.rhs); |
| 5170 | const ptr = if (ptr_ty.isSinglePointer()) ptr: { | 5200 | const ptr = if (ptr_ty.isSinglePointer()) ptr: { |
| 5171 | // If this is a single-item pointer to an array, we need another index in the GEP. | 5201 | // If this is a single-item pointer to an array, we need another index in the GEP. |
| 5172 | const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; | 5202 | const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| 5173 | break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 5203 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5174 | } else ptr: { | 5204 | } else ptr: { |
| 5175 | const indices: [1]*const llvm.Value = .{rhs}; | 5205 | const indices: [1]*const llvm.Value = .{rhs}; |
| 5176 | break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 5206 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5177 | }; | 5207 | }; |
| 5178 | return self.load(ptr, ptr_ty); | 5208 | return self.load(ptr, ptr_ty); |
| 5179 | } | 5209 | } |
| ... | @@ -5189,13 +5219,14 @@ pub const FuncGen = struct { | ... | @@ -5189,13 +5219,14 @@ pub const FuncGen = struct { |
| 5189 | | 5219 | |
| 5190 | const base_ptr = try self.resolveInst(bin_op.lhs); | 5220 | const base_ptr = try self.resolveInst(bin_op.lhs); |
| 5191 | const rhs = try self.resolveInst(bin_op.rhs); | 5221 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 5222 | const llvm_elem_ty = try self.dg.lowerType(elem_ty); |
| 5192 | if (ptr_ty.isSinglePointer()) { | 5223 | if (ptr_ty.isSinglePointer()) { |
| 5193 | // If this is a single-item pointer to an array, we need another index in the GEP. | 5224 | // If this is a single-item pointer to an array, we need another index in the GEP. |
| 5194 | const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; | 5225 | const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| 5195 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 5226 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5196 | } else { | 5227 | } else { |
| 5197 | const indices: [1]*const llvm.Value = .{rhs}; | 5228 | const indices: [1]*const llvm.Value = .{rhs}; |
| 5198 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 5229 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 5199 | } | 5230 | } |
| 5200 | } | 5231 | } |
| 5201 | | 5232 | |
| ... | @@ -5279,20 +5310,22 @@ pub const FuncGen = struct { | ... | @@ -5279,20 +5310,22 @@ pub const FuncGen = struct { |
| 5279 | assert(struct_ty.containerLayout() != .Packed); | 5310 | assert(struct_ty.containerLayout() != .Packed); |
| 5280 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 5311 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 5281 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; | 5312 | const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; |
| 5282 | const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); | 5313 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); |
| | 5314 | const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); |
| 5283 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); | 5315 | const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); |
| 5284 | return self.load(field_ptr, field_ptr_ty); | 5316 | return self.load(field_ptr, field_ptr_ty); |
| 5285 | }, | 5317 | }, |
| 5286 | .Union => { | 5318 | .Union => { |
| 5287 | const llvm_field_ty = try self.dg.lowerType(field_ty); | 5319 | const union_llvm_ty = try self.dg.lowerType(struct_ty); |
| 5288 | const layout = struct_ty.unionGetLayout(target); | 5320 | const layout = struct_ty.unionGetLayout(target); |
| 5289 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 5321 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 5290 | const union_field_ptr = self.builder.buildStructGEP(struct_llvm_val, payload_index, ""); | 5322 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); |
| | 5323 | const llvm_field_ty = try self.dg.lowerType(field_ty); |
| 5291 | const field_ptr = self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); | 5324 | const field_ptr = self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); |
| 5292 | if (isByRef(field_ty)) { | 5325 | if (isByRef(field_ty)) { |
| 5293 | return field_ptr; | 5326 | return field_ptr; |
| 5294 | } else { | 5327 | } else { |
| 5295 | return self.builder.buildLoad(field_ptr, ""); | 5328 | return self.builder.buildLoad(llvm_field_ty, field_ptr, ""); |
| 5296 | } | 5329 | } |
| 5297 | }, | 5330 | }, |
| 5298 | else => unreachable, | 5331 | else => unreachable, |
| ... | @@ -5605,10 +5638,11 @@ pub const FuncGen = struct { | ... | @@ -5605,10 +5638,11 @@ pub const FuncGen = struct { |
| 5605 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); | 5638 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| 5606 | } else { | 5639 | } else { |
| 5607 | const alignment = arg_ty.abiAlignment(target); | 5640 | const alignment = arg_ty.abiAlignment(target); |
| 5608 | const load_inst = self.builder.buildLoad(arg_llvm_value, ""); | 5641 | const arg_llvm_ty = try self.dg.lowerType(arg_ty); |
| | 5642 | const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, ""); |
| 5609 | load_inst.setAlignment(alignment); | 5643 | load_inst.setAlignment(alignment); |
| 5610 | llvm_param_values[llvm_param_i] = load_inst; | 5644 | llvm_param_values[llvm_param_i] = load_inst; |
| 5611 | llvm_param_types[llvm_param_i] = load_inst.typeOf(); | 5645 | llvm_param_types[llvm_param_i] = arg_llvm_ty; |
| 5612 | } | 5646 | } |
| 5613 | } else { | 5647 | } else { |
| 5614 | if (constraintAllowsRegister(constraint)) { | 5648 | if (constraintAllowsRegister(constraint)) { |
| ... | @@ -5769,6 +5803,7 @@ pub const FuncGen = struct { | ... | @@ -5769,6 +5803,7 @@ pub const FuncGen = struct { |
| 5769 | .False, | 5803 | .False, |
| 5770 | ); | 5804 | ); |
| 5771 | const call = self.builder.buildCall( | 5805 | const call = self.builder.buildCall( |
| | 5806 | asm_fn.typeOf(), |
| 5772 | asm_fn, | 5807 | asm_fn, |
| 5773 | llvm_param_values.ptr, | 5808 | llvm_param_values.ptr, |
| 5774 | @intCast(c_uint, param_count), | 5809 | @intCast(c_uint, param_count), |
| ... | @@ -5819,9 +5854,12 @@ pub const FuncGen = struct { | ... | @@ -5819,9 +5854,12 @@ pub const FuncGen = struct { |
| 5819 | const operand = try self.resolveInst(un_op); | 5854 | const operand = try self.resolveInst(un_op); |
| 5820 | const operand_ty = self.air.typeOf(un_op); | 5855 | const operand_ty = self.air.typeOf(un_op); |
| 5821 | const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; | 5856 | const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| | 5857 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| 5822 | if (optional_ty.optionalReprIsPayload()) { | 5858 | if (optional_ty.optionalReprIsPayload()) { |
| 5823 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); | 5859 | const loaded = if (operand_is_ptr) |
| 5824 | const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; | 5860 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| | 5861 | else |
| | 5862 | operand; |
| 5825 | return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); | 5863 | return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); |
| 5826 | } | 5864 | } |
| 5827 | | 5865 | |
| ... | @@ -5830,13 +5868,16 @@ pub const FuncGen = struct { | ... | @@ -5830,13 +5868,16 @@ pub const FuncGen = struct { |
| 5830 | var buf: Type.Payload.ElemType = undefined; | 5868 | var buf: Type.Payload.ElemType = undefined; |
| 5831 | const payload_ty = optional_ty.optionalChild(&buf); | 5869 | const payload_ty = optional_ty.optionalChild(&buf); |
| 5832 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 5870 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 5833 | const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; | 5871 | const loaded = if (operand_is_ptr) |
| | 5872 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| | 5873 | else |
| | 5874 | operand; |
| 5834 | const llvm_i8 = self.dg.context.intType(8); | 5875 | const llvm_i8 = self.dg.context.intType(8); |
| 5835 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); | 5876 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); |
| 5836 | } | 5877 | } |
| 5837 | | 5878 | |
| 5838 | const is_by_ref = operand_is_ptr or isByRef(optional_ty); | 5879 | const is_by_ref = operand_is_ptr or isByRef(optional_ty); |
| 5839 | const non_null_bit = self.optIsNonNull(operand, is_by_ref); | 5880 | const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); |
| 5840 | if (pred == .EQ) { | 5881 | if (pred == .EQ) { |
| 5841 | return self.builder.buildNot(non_null_bit, ""); | 5882 | return self.builder.buildNot(non_null_bit, ""); |
| 5842 | } else { | 5883 | } else { |
| ... | @@ -5857,7 +5898,7 @@ pub const FuncGen = struct { | ... | @@ -5857,7 +5898,7 @@ pub const FuncGen = struct { |
| 5857 | const operand_ty = self.air.typeOf(un_op); | 5898 | const operand_ty = self.air.typeOf(un_op); |
| 5858 | const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; | 5899 | const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; |
| 5859 | const payload_ty = err_union_ty.errorUnionPayload(); | 5900 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 5860 | const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror)); | 5901 | const err_set_ty = try self.dg.lowerType(Type.anyerror); |
| 5861 | const zero = err_set_ty.constNull(); | 5902 | const zero = err_set_ty.constNull(); |
| 5862 | | 5903 | |
| 5863 | if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { | 5904 | if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { |
| ... | @@ -5870,7 +5911,10 @@ pub const FuncGen = struct { | ... | @@ -5870,7 +5911,10 @@ pub const FuncGen = struct { |
| 5870 | } | 5911 | } |
| 5871 | | 5912 | |
| 5872 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 5913 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 5873 | const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; | 5914 | const loaded = if (operand_is_ptr) |
| | 5915 | self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") |
| | 5916 | else |
| | 5917 | operand; |
| 5874 | return self.builder.buildICmp(op, loaded, zero, ""); | 5918 | return self.builder.buildICmp(op, loaded, zero, ""); |
| 5875 | } | 5919 | } |
| 5876 | | 5920 | |
| ... | @@ -5878,8 +5922,9 @@ pub const FuncGen = struct { | ... | @@ -5878,8 +5922,9 @@ pub const FuncGen = struct { |
| 5878 | const err_field_index = errUnionErrorOffset(payload_ty, target); | 5922 | const err_field_index = errUnionErrorOffset(payload_ty, target); |
| 5879 | | 5923 | |
| 5880 | if (operand_is_ptr or isByRef(err_union_ty)) { | 5924 | if (operand_is_ptr or isByRef(err_union_ty)) { |
| 5881 | const err_field_ptr = self.builder.buildStructGEP(operand, err_field_index, ""); | 5925 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 5882 | const loaded = self.builder.buildLoad(err_field_ptr, ""); | 5926 | const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, ""); |
| | 5927 | const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, ""); |
| 5883 | return self.builder.buildICmp(op, loaded, zero, ""); | 5928 | return self.builder.buildICmp(op, loaded, zero, ""); |
| 5884 | } | 5929 | } |
| 5885 | | 5930 | |
| ... | @@ -5900,7 +5945,7 @@ pub const FuncGen = struct { | ... | @@ -5900,7 +5945,7 @@ pub const FuncGen = struct { |
| 5900 | // We have a pointer to a zero-bit value and we need to return | 5945 | // We have a pointer to a zero-bit value and we need to return |
| 5901 | // a pointer to a zero-bit value. | 5946 | // a pointer to a zero-bit value. |
| 5902 | | 5947 | |
| 5903 | // TODO once we update to LLVM 14 this bitcast won't be necessary. | 5948 | // TODO once we update to LLVM 16 this bitcast won't be necessary. |
| 5904 | const res_ptr_ty = try self.dg.lowerType(result_ty); | 5949 | const res_ptr_ty = try self.dg.lowerType(result_ty); |
| 5905 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); | 5950 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); |
| 5906 | } | 5951 | } |
| ... | @@ -5908,7 +5953,8 @@ pub const FuncGen = struct { | ... | @@ -5908,7 +5953,8 @@ pub const FuncGen = struct { |
| 5908 | // The payload and the optional are the same value. | 5953 | // The payload and the optional are the same value. |
| 5909 | return operand; | 5954 | return operand; |
| 5910 | } | 5955 | } |
| 5911 | return self.builder.buildStructGEP(operand, 0, ""); | 5956 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| | 5957 | return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); |
| 5912 | } | 5958 | } |
| 5913 | | 5959 | |
| 5914 | fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 5960 | fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -5925,7 +5971,7 @@ pub const FuncGen = struct { | ... | @@ -5925,7 +5971,7 @@ pub const FuncGen = struct { |
| 5925 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. | 5971 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 5926 | _ = self.builder.buildStore(non_null_bit, operand); | 5972 | _ = self.builder.buildStore(non_null_bit, operand); |
| 5927 | | 5973 | |
| 5928 | // TODO once we update to LLVM 14 this bitcast won't be necessary. | 5974 | // TODO once we update to LLVM 16 this bitcast won't be necessary. |
| 5929 | const res_ptr_ty = try self.dg.lowerType(result_ty); | 5975 | const res_ptr_ty = try self.dg.lowerType(result_ty); |
| 5930 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); | 5976 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); |
| 5931 | } | 5977 | } |
| ... | @@ -5936,7 +5982,8 @@ pub const FuncGen = struct { | ... | @@ -5936,7 +5982,8 @@ pub const FuncGen = struct { |
| 5936 | } | 5982 | } |
| 5937 | | 5983 | |
| 5938 | // First set the non-null bit. | 5984 | // First set the non-null bit. |
| 5939 | const non_null_ptr = self.builder.buildStructGEP(operand, 1, ""); | 5985 | const optional_llvm_ty = try self.dg.lowerType(optional_ty); |
| | 5986 | const non_null_ptr = self.builder.buildStructGEP(optional_llvm_ty, operand, 1, ""); |
| 5940 | // TODO set alignment on this store | 5987 | // TODO set alignment on this store |
| 5941 | _ = self.builder.buildStore(non_null_bit, non_null_ptr); | 5988 | _ = self.builder.buildStore(non_null_bit, non_null_ptr); |
| 5942 | | 5989 | |
| ... | @@ -5944,7 +5991,7 @@ pub const FuncGen = struct { | ... | @@ -5944,7 +5991,7 @@ pub const FuncGen = struct { |
| 5944 | if (self.liveness.isUnused(inst)) | 5991 | if (self.liveness.isUnused(inst)) |
| 5945 | return null; | 5992 | return null; |
| 5946 | | 5993 | |
| 5947 | return self.builder.buildStructGEP(operand, 0, ""); | 5994 | return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); |
| 5948 | } | 5995 | } |
| 5949 | | 5996 | |
| 5950 | fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 5997 | fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -5961,7 +6008,8 @@ pub const FuncGen = struct { | ... | @@ -5961,7 +6008,8 @@ pub const FuncGen = struct { |
| 5961 | return operand; | 6008 | return operand; |
| 5962 | } | 6009 | } |
| 5963 | | 6010 | |
| 5964 | return self.optPayloadHandle(operand, optional_ty); | 6011 | const opt_llvm_ty = try self.dg.lowerType(optional_ty); |
| | 6012 | return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty); |
| 5965 | } | 6013 | } |
| 5966 | | 6014 | |
| 5967 | fn airErrUnionPayload( | 6015 | fn airErrUnionPayload( |
| ... | @@ -5987,14 +6035,15 @@ pub const FuncGen = struct { | ... | @@ -5987,14 +6035,15 @@ pub const FuncGen = struct { |
| 5987 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); | 6035 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); |
| 5988 | } | 6036 | } |
| 5989 | const offset = errUnionPayloadOffset(payload_ty, target); | 6037 | const offset = errUnionPayloadOffset(payload_ty, target); |
| | 6038 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 5990 | if (operand_is_ptr or isByRef(payload_ty)) { | 6039 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 5991 | return self.builder.buildStructGEP(operand, offset, ""); | 6040 | return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); |
| 5992 | } else if (isByRef(err_union_ty)) { | 6041 | } else if (isByRef(err_union_ty)) { |
| 5993 | const payload_ptr = self.builder.buildStructGEP(operand, offset, ""); | 6042 | const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); |
| 5994 | if (isByRef(payload_ty)) { | 6043 | if (isByRef(payload_ty)) { |
| 5995 | return payload_ptr; | 6044 | return payload_ptr; |
| 5996 | } | 6045 | } |
| 5997 | const load_inst = self.builder.buildLoad(payload_ptr, ""); | 6046 | const load_inst = self.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); |
| 5998 | load_inst.setAlignment(payload_ty.abiAlignment(target)); | 6047 | load_inst.setAlignment(payload_ty.abiAlignment(target)); |
| 5999 | return load_inst; | 6048 | return load_inst; |
| 6000 | } | 6049 | } |
| ... | @@ -6022,18 +6071,21 @@ pub const FuncGen = struct { | ... | @@ -6022,18 +6071,21 @@ pub const FuncGen = struct { |
| 6022 | } | 6071 | } |
| 6023 | } | 6072 | } |
| 6024 | | 6073 | |
| | 6074 | const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); |
| | 6075 | |
| 6025 | const payload_ty = err_union_ty.errorUnionPayload(); | 6076 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 6026 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6077 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 6027 | if (!operand_is_ptr) return operand; | 6078 | if (!operand_is_ptr) return operand; |
| 6028 | return self.builder.buildLoad(operand, ""); | 6079 | return self.builder.buildLoad(err_set_llvm_ty, operand, ""); |
| 6029 | } | 6080 | } |
| 6030 | | 6081 | |
| 6031 | const target = self.dg.module.getTarget(); | 6082 | const target = self.dg.module.getTarget(); |
| 6032 | const offset = errUnionErrorOffset(payload_ty, target); | 6083 | const offset = errUnionErrorOffset(payload_ty, target); |
| 6033 | | 6084 | |
| 6034 | if (operand_is_ptr or isByRef(err_union_ty)) { | 6085 | if (operand_is_ptr or isByRef(err_union_ty)) { |
| 6035 | const err_field_ptr = self.builder.buildStructGEP(operand, offset, ""); | 6086 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 6036 | return self.builder.buildLoad(err_field_ptr, ""); | 6087 | const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); |
| | 6088 | return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, ""); |
| 6037 | } | 6089 | } |
| 6038 | | 6090 | |
| 6039 | return self.builder.buildExtractValue(operand, offset, ""); | 6091 | return self.builder.buildExtractValue(operand, offset, ""); |
| ... | @@ -6042,19 +6094,20 @@ pub const FuncGen = struct { | ... | @@ -6042,19 +6094,20 @@ pub const FuncGen = struct { |
| 6042 | fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 6094 | fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 6043 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 6095 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6044 | const operand = try self.resolveInst(ty_op.operand); | 6096 | const operand = try self.resolveInst(ty_op.operand); |
| 6045 | const error_union_ty = self.air.typeOf(ty_op.operand).childType(); | 6097 | const err_union_ty = self.air.typeOf(ty_op.operand).childType(); |
| 6046 | | 6098 | |
| 6047 | const payload_ty = error_union_ty.errorUnionPayload(); | 6099 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 6048 | const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); | 6100 | const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); |
| 6049 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 6101 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 6050 | _ = self.builder.buildStore(non_error_val, operand); | 6102 | _ = self.builder.buildStore(non_error_val, operand); |
| 6051 | return operand; | 6103 | return operand; |
| 6052 | } | 6104 | } |
| 6053 | const target = self.dg.module.getTarget(); | 6105 | const target = self.dg.module.getTarget(); |
| | 6106 | const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); |
| 6054 | { | 6107 | { |
| 6055 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6108 | const error_offset = errUnionErrorOffset(payload_ty, target); |
| 6056 | // First set the non-error value. | 6109 | // First set the non-error value. |
| 6057 | const non_null_ptr = self.builder.buildStructGEP(operand, error_offset, ""); | 6110 | const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, ""); |
| 6058 | const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); | 6111 | const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); |
| 6059 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6112 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); |
| 6060 | } | 6113 | } |
| ... | @@ -6063,7 +6116,7 @@ pub const FuncGen = struct { | ... | @@ -6063,7 +6116,7 @@ pub const FuncGen = struct { |
| 6063 | return null; | 6116 | return null; |
| 6064 | | 6117 | |
| 6065 | const payload_offset = errUnionPayloadOffset(payload_ty, target); | 6118 | const payload_offset = errUnionPayloadOffset(payload_ty, target); |
| 6066 | return self.builder.buildStructGEP(operand, payload_offset, ""); | 6119 | return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, ""); |
| 6067 | } | 6120 | } |
| 6068 | | 6121 | |
| 6069 | fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { | 6122 | fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -6093,14 +6146,14 @@ pub const FuncGen = struct { | ... | @@ -6093,14 +6146,14 @@ pub const FuncGen = struct { |
| 6093 | const llvm_optional_ty = try self.dg.lowerType(optional_ty); | 6146 | const llvm_optional_ty = try self.dg.lowerType(optional_ty); |
| 6094 | if (isByRef(optional_ty)) { | 6147 | if (isByRef(optional_ty)) { |
| 6095 | const optional_ptr = self.buildAlloca(llvm_optional_ty); | 6148 | const optional_ptr = self.buildAlloca(llvm_optional_ty); |
| 6096 | const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, ""); | 6149 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); |
| 6097 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 6150 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6098 | .base = .{ .tag = .single_mut_pointer }, | 6151 | .base = .{ .tag = .single_mut_pointer }, |
| 6099 | .data = payload_ty, | 6152 | .data = payload_ty, |
| 6100 | }; | 6153 | }; |
| 6101 | const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base); | 6154 | const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 6102 | self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); | 6155 | self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); |
| 6103 | const non_null_ptr = self.builder.buildStructGEP(optional_ptr, 1, ""); | 6156 | const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, ""); |
| 6104 | _ = self.builder.buildStore(non_null_bit, non_null_ptr); | 6157 | _ = self.builder.buildStore(non_null_bit, non_null_ptr); |
| 6105 | return optional_ptr; | 6158 | return optional_ptr; |
| 6106 | } | 6159 | } |
| ... | @@ -6126,10 +6179,10 @@ pub const FuncGen = struct { | ... | @@ -6126,10 +6179,10 @@ pub const FuncGen = struct { |
| 6126 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6179 | const error_offset = errUnionErrorOffset(payload_ty, target); |
| 6127 | if (isByRef(inst_ty)) { | 6180 | if (isByRef(inst_ty)) { |
| 6128 | const result_ptr = self.buildAlloca(err_un_llvm_ty); | 6181 | const result_ptr = self.buildAlloca(err_un_llvm_ty); |
| 6129 | const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); | 6182 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 6130 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); | 6183 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); |
| 6131 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6184 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); |
| 6132 | const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); | 6185 | const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); |
| 6133 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 6186 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6134 | .base = .{ .tag = .single_mut_pointer }, | 6187 | .base = .{ .tag = .single_mut_pointer }, |
| 6135 | .data = payload_ty, | 6188 | .data = payload_ty, |
| ... | @@ -6160,10 +6213,10 @@ pub const FuncGen = struct { | ... | @@ -6160,10 +6213,10 @@ pub const FuncGen = struct { |
| 6160 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6213 | const error_offset = errUnionErrorOffset(payload_ty, target); |
| 6161 | if (isByRef(err_un_ty)) { | 6214 | if (isByRef(err_un_ty)) { |
| 6162 | const result_ptr = self.buildAlloca(err_un_llvm_ty); | 6215 | const result_ptr = self.buildAlloca(err_un_llvm_ty); |
| 6163 | const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); | 6216 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 6164 | const store_inst = self.builder.buildStore(operand, err_ptr); | 6217 | const store_inst = self.builder.buildStore(operand, err_ptr); |
| 6165 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6218 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); |
| 6166 | const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); | 6219 | const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); |
| 6167 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 6220 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6168 | .base = .{ .tag = .single_mut_pointer }, | 6221 | .base = .{ .tag = .single_mut_pointer }, |
| 6169 | .data = payload_ty, | 6222 | .data = payload_ty, |
| ... | @@ -6188,7 +6241,7 @@ pub const FuncGen = struct { | ... | @@ -6188,7 +6241,7 @@ pub const FuncGen = struct { |
| 6188 | const llvm_u32 = self.context.intType(32); | 6241 | const llvm_u32 = self.context.intType(32); |
| 6189 | const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); | 6242 | const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); |
| 6190 | const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; | 6243 | const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; |
| 6191 | return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); | 6244 | return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 6192 | } | 6245 | } |
| 6193 | | 6246 | |
| 6194 | fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 6247 | fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -6201,7 +6254,7 @@ pub const FuncGen = struct { | ... | @@ -6201,7 +6254,7 @@ pub const FuncGen = struct { |
| 6201 | llvm_u32.constInt(index, .False), | 6254 | llvm_u32.constInt(index, .False), |
| 6202 | operand, | 6255 | operand, |
| 6203 | }; | 6256 | }; |
| 6204 | return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); | 6257 | return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 6205 | } | 6258 | } |
| 6206 | | 6259 | |
| 6207 | fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 6260 | fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -6504,15 +6557,16 @@ pub const FuncGen = struct { | ... | @@ -6504,15 +6557,16 @@ pub const FuncGen = struct { |
| 6504 | const base_ptr = try self.resolveInst(bin_op.lhs); | 6557 | const base_ptr = try self.resolveInst(bin_op.lhs); |
| 6505 | const offset = try self.resolveInst(bin_op.rhs); | 6558 | const offset = try self.resolveInst(bin_op.rhs); |
| 6506 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 6559 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| | 6560 | const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); |
| 6507 | if (ptr_ty.ptrSize() == .One) { | 6561 | if (ptr_ty.ptrSize() == .One) { |
| 6508 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | 6562 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 6509 | const indices: [2]*const llvm.Value = .{ | 6563 | const indices: [2]*const llvm.Value = .{ |
| 6510 | self.context.intType(32).constNull(), offset, | 6564 | self.context.intType(32).constNull(), offset, |
| 6511 | }; | 6565 | }; |
| 6512 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 6566 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6513 | } else { | 6567 | } else { |
| 6514 | const indices: [1]*const llvm.Value = .{offset}; | 6568 | const indices: [1]*const llvm.Value = .{offset}; |
| 6515 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 6569 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6516 | } | 6570 | } |
| 6517 | } | 6571 | } |
| 6518 | | 6572 | |
| ... | @@ -6525,15 +6579,16 @@ pub const FuncGen = struct { | ... | @@ -6525,15 +6579,16 @@ pub const FuncGen = struct { |
| 6525 | const offset = try self.resolveInst(bin_op.rhs); | 6579 | const offset = try self.resolveInst(bin_op.rhs); |
| 6526 | const negative_offset = self.builder.buildNeg(offset, ""); | 6580 | const negative_offset = self.builder.buildNeg(offset, ""); |
| 6527 | const ptr_ty = self.air.typeOf(bin_op.lhs); | 6581 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| | 6582 | const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); |
| 6528 | if (ptr_ty.ptrSize() == .One) { | 6583 | if (ptr_ty.ptrSize() == .One) { |
| 6529 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | 6584 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 6530 | const indices: [2]*const llvm.Value = .{ | 6585 | const indices: [2]*const llvm.Value = .{ |
| 6531 | self.context.intType(32).constNull(), negative_offset, | 6586 | self.context.intType(32).constNull(), negative_offset, |
| 6532 | }; | 6587 | }; |
| 6533 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 6588 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6534 | } else { | 6589 | } else { |
| 6535 | const indices: [1]*const llvm.Value = .{negative_offset}; | 6590 | const indices: [1]*const llvm.Value = .{negative_offset}; |
| 6536 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | 6591 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6537 | } | 6592 | } |
| 6538 | } | 6593 | } |
| 6539 | | 6594 | |
| ... | @@ -6564,7 +6619,7 @@ pub const FuncGen = struct { | ... | @@ -6564,7 +6619,7 @@ pub const FuncGen = struct { |
| 6564 | const tg = self.dg.module.getTarget(); | 6619 | const tg = self.dg.module.getTarget(); |
| 6565 | | 6620 | |
| 6566 | const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); | 6621 | const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); |
| 6567 | const result_struct = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); | 6622 | const result_struct = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); |
| 6568 | | 6623 | |
| 6569 | const result = self.builder.buildExtractValue(result_struct, 0, ""); | 6624 | const result = self.builder.buildExtractValue(result_struct, 0, ""); |
| 6570 | const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); | 6625 | const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); |
| ... | @@ -6579,12 +6634,12 @@ pub const FuncGen = struct { | ... | @@ -6579,12 +6634,12 @@ pub const FuncGen = struct { |
| 6579 | const result_alignment = dest_ty.abiAlignment(target); | 6634 | const result_alignment = dest_ty.abiAlignment(target); |
| 6580 | alloca_inst.setAlignment(result_alignment); | 6635 | alloca_inst.setAlignment(result_alignment); |
| 6581 | { | 6636 | { |
| 6582 | const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); | 6637 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 6583 | const store_inst = self.builder.buildStore(result, field_ptr); | 6638 | const store_inst = self.builder.buildStore(result, field_ptr); |
| 6584 | store_inst.setAlignment(result_alignment); | 6639 | store_inst.setAlignment(result_alignment); |
| 6585 | } | 6640 | } |
| 6586 | { | 6641 | { |
| 6587 | const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); | 6642 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); |
| 6588 | const store_inst = self.builder.buildStore(overflow_bit, field_ptr); | 6643 | const store_inst = self.builder.buildStore(overflow_bit, field_ptr); |
| 6589 | store_inst.setAlignment(1); | 6644 | store_inst.setAlignment(1); |
| 6590 | } | 6645 | } |
| ... | @@ -6616,7 +6671,7 @@ pub const FuncGen = struct { | ... | @@ -6616,7 +6671,7 @@ pub const FuncGen = struct { |
| 6616 | for (args_vectors) |arg_vector, k| { | 6671 | for (args_vectors) |arg_vector, k| { |
| 6617 | args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); | 6672 | args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); |
| 6618 | } | 6673 | } |
| 6619 | const result_elem = self.builder.buildCall(llvm_fn, &args, args_len, .C, .Auto, ""); | 6674 | const result_elem = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args_len, .C, .Auto, ""); |
| 6620 | result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); | 6675 | result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); |
| 6621 | } | 6676 | } |
| 6622 | return result; | 6677 | return result; |
| ... | @@ -6743,7 +6798,7 @@ pub const FuncGen = struct { | ... | @@ -6743,7 +6798,7 @@ pub const FuncGen = struct { |
| 6743 | return self.builder.buildICmp(int_pred, result, zero_vector, ""); | 6798 | return self.builder.buildICmp(int_pred, result, zero_vector, ""); |
| 6744 | } | 6799 | } |
| 6745 | | 6800 | |
| 6746 | const result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, ""); | 6801 | const result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, &params, params.len, .C, .Auto, ""); |
| 6747 | return self.builder.buildICmp(int_pred, result, zero, ""); | 6802 | return self.builder.buildICmp(int_pred, result, zero, ""); |
| 6748 | } | 6803 | } |
| 6749 | | 6804 | |
| ... | @@ -6871,7 +6926,7 @@ pub const FuncGen = struct { | ... | @@ -6871,7 +6926,7 @@ pub const FuncGen = struct { |
| 6871 | break :b libc_fn; | 6926 | break :b libc_fn; |
| 6872 | }, | 6927 | }, |
| 6873 | }; | 6928 | }; |
| 6874 | return self.builder.buildCall(llvm_fn, &params, params_len, .C, .Auto, ""); | 6929 | return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &params, params_len, .C, .Auto, ""); |
| 6875 | } | 6930 | } |
| 6876 | | 6931 | |
| 6877 | fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 6932 | fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -6931,12 +6986,12 @@ pub const FuncGen = struct { | ... | @@ -6931,12 +6986,12 @@ pub const FuncGen = struct { |
| 6931 | const result_alignment = dest_ty.abiAlignment(target); | 6986 | const result_alignment = dest_ty.abiAlignment(target); |
| 6932 | alloca_inst.setAlignment(result_alignment); | 6987 | alloca_inst.setAlignment(result_alignment); |
| 6933 | { | 6988 | { |
| 6934 | const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); | 6989 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 6935 | const store_inst = self.builder.buildStore(result, field_ptr); | 6990 | const store_inst = self.builder.buildStore(result, field_ptr); |
| 6936 | store_inst.setAlignment(result_alignment); | 6991 | store_inst.setAlignment(result_alignment); |
| 6937 | } | 6992 | } |
| 6938 | { | 6993 | { |
| 6939 | const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); | 6994 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); |
| 6940 | const store_inst = self.builder.buildStore(overflow_bit, field_ptr); | 6995 | const store_inst = self.builder.buildStore(overflow_bit, field_ptr); |
| 6941 | store_inst.setAlignment(1); | 6996 | store_inst.setAlignment(1); |
| 6942 | } | 6997 | } |
| ... | @@ -7226,7 +7281,7 @@ pub const FuncGen = struct { | ... | @@ -7226,7 +7281,7 @@ pub const FuncGen = struct { |
| 7226 | const index_usize = llvm_usize.constInt(i, .False); | 7281 | const index_usize = llvm_usize.constInt(i, .False); |
| 7227 | const index_u32 = llvm_u32.constInt(i, .False); | 7282 | const index_u32 = llvm_u32.constInt(i, .False); |
| 7228 | const indexes: [2]*const llvm.Value = .{ zero, index_usize }; | 7283 | const indexes: [2]*const llvm.Value = .{ zero, index_usize }; |
| 7229 | const elem_ptr = self.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); | 7284 | const elem_ptr = self.builder.buildInBoundsGEP(llvm_dest_ty, array_ptr, &indexes, indexes.len, ""); |
| 7230 | const elem = self.builder.buildExtractElement(operand, index_u32, ""); | 7285 | const elem = self.builder.buildExtractElement(operand, index_u32, ""); |
| 7231 | _ = self.builder.buildStore(elem, elem_ptr); | 7286 | _ = self.builder.buildStore(elem, elem_ptr); |
| 7232 | } | 7287 | } |
| ... | @@ -7243,7 +7298,7 @@ pub const FuncGen = struct { | ... | @@ -7243,7 +7298,7 @@ pub const FuncGen = struct { |
| 7243 | if (bitcast_ok) { | 7298 | if (bitcast_ok) { |
| 7244 | const llvm_vector_ptr_ty = llvm_vector_ty.pointerType(0); | 7299 | const llvm_vector_ptr_ty = llvm_vector_ty.pointerType(0); |
| 7245 | const casted_ptr = self.builder.buildBitCast(operand, llvm_vector_ptr_ty, ""); | 7300 | const casted_ptr = self.builder.buildBitCast(operand, llvm_vector_ptr_ty, ""); |
| 7246 | const vector = self.builder.buildLoad(casted_ptr, ""); | 7301 | const vector = self.builder.buildLoad(llvm_vector_ty, casted_ptr, ""); |
| 7247 | // The array is aligned to the element's alignment, while the vector might have a completely | 7302 | // The array is aligned to the element's alignment, while the vector might have a completely |
| 7248 | // different alignment. This means we need to enforce the alignment of this load. | 7303 | // different alignment. This means we need to enforce the alignment of this load. |
| 7249 | vector.setAlignment(elem_ty.abiAlignment(target)); | 7304 | vector.setAlignment(elem_ty.abiAlignment(target)); |
| ... | @@ -7251,6 +7306,7 @@ pub const FuncGen = struct { | ... | @@ -7251,6 +7306,7 @@ pub const FuncGen = struct { |
| 7251 | } else { | 7306 | } else { |
| 7252 | // If the ABI size of the element type is not evenly divisible by size in bits; | 7307 | // If the ABI size of the element type is not evenly divisible by size in bits; |
| 7253 | // a simple bitcast will not work, and we fall back to extractelement. | 7308 | // a simple bitcast will not work, and we fall back to extractelement. |
| | 7309 | const elem_llvm_ty = try self.dg.lowerType(elem_ty); |
| 7254 | const llvm_usize = try self.dg.lowerType(Type.usize); | 7310 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 7255 | const llvm_u32 = self.context.intType(32); | 7311 | const llvm_u32 = self.context.intType(32); |
| 7256 | const zero = llvm_usize.constNull(); | 7312 | const zero = llvm_usize.constNull(); |
| ... | @@ -7261,8 +7317,8 @@ pub const FuncGen = struct { | ... | @@ -7261,8 +7317,8 @@ pub const FuncGen = struct { |
| 7261 | const index_usize = llvm_usize.constInt(i, .False); | 7317 | const index_usize = llvm_usize.constInt(i, .False); |
| 7262 | const index_u32 = llvm_u32.constInt(i, .False); | 7318 | const index_u32 = llvm_u32.constInt(i, .False); |
| 7263 | const indexes: [2]*const llvm.Value = .{ zero, index_usize }; | 7319 | const indexes: [2]*const llvm.Value = .{ zero, index_usize }; |
| 7264 | const elem_ptr = self.builder.buildInBoundsGEP(operand, &indexes, indexes.len, ""); | 7320 | const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indexes, indexes.len, ""); |
| 7265 | const elem = self.builder.buildLoad(elem_ptr, ""); | 7321 | const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); |
| 7266 | vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); | 7322 | vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); |
| 7267 | } | 7323 | } |
| 7268 | | 7324 | |
| ... | @@ -7273,7 +7329,7 @@ pub const FuncGen = struct { | ... | @@ -7273,7 +7329,7 @@ pub const FuncGen = struct { |
| 7273 | if (operand_is_ref) { | 7329 | if (operand_is_ref) { |
| 7274 | // Bitcast the operand pointer, then load. | 7330 | // Bitcast the operand pointer, then load. |
| 7275 | const casted_ptr = self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), ""); | 7331 | const casted_ptr = self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), ""); |
| 7276 | const load_inst = self.builder.buildLoad(casted_ptr, ""); | 7332 | const load_inst = self.builder.buildLoad(llvm_dest_ty, casted_ptr, ""); |
| 7277 | load_inst.setAlignment(operand_ty.abiAlignment(target)); | 7333 | load_inst.setAlignment(operand_ty.abiAlignment(target)); |
| 7278 | return load_inst; | 7334 | return load_inst; |
| 7279 | } | 7335 | } |
| ... | @@ -7301,7 +7357,7 @@ pub const FuncGen = struct { | ... | @@ -7301,7 +7357,7 @@ pub const FuncGen = struct { |
| 7301 | const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); | 7357 | const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); |
| 7302 | const store_inst = self.builder.buildStore(operand, casted_ptr); | 7358 | const store_inst = self.builder.buildStore(operand, casted_ptr); |
| 7303 | store_inst.setAlignment(alignment); | 7359 | store_inst.setAlignment(alignment); |
| 7304 | const load_inst = self.builder.buildLoad(result_ptr, ""); | 7360 | const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); |
| 7305 | load_inst.setAlignment(alignment); | 7361 | load_inst.setAlignment(alignment); |
| 7306 | return load_inst; | 7362 | return load_inst; |
| 7307 | } | 7363 | } |
| ... | @@ -7481,7 +7537,7 @@ pub const FuncGen = struct { | ... | @@ -7481,7 +7537,7 @@ pub const FuncGen = struct { |
| 7481 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 7537 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 7482 | _ = inst; | 7538 | _ = inst; |
| 7483 | const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); | 7539 | const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); |
| 7484 | _ = self.builder.buildCall(llvm_fn, undefined, 0, .C, .Auto, ""); | 7540 | _ = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, undefined, 0, .C, .Auto, ""); |
| 7485 | return null; | 7541 | return null; |
| 7486 | } | 7542 | } |
| 7487 | | 7543 | |
| ... | @@ -7498,7 +7554,7 @@ pub const FuncGen = struct { | ... | @@ -7498,7 +7554,7 @@ pub const FuncGen = struct { |
| 7498 | const llvm_i32 = self.context.intType(32); | 7554 | const llvm_i32 = self.context.intType(32); |
| 7499 | const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); | 7555 | const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); |
| 7500 | const params = [_]*const llvm.Value{llvm_i32.constNull()}; | 7556 | const params = [_]*const llvm.Value{llvm_i32.constNull()}; |
| 7501 | const ptr_val = self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, ""); | 7557 | const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 7502 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); | 7558 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); |
| 7503 | } | 7559 | } |
| 7504 | | 7560 | |
| ... | @@ -7515,7 +7571,7 @@ pub const FuncGen = struct { | ... | @@ -7515,7 +7571,7 @@ pub const FuncGen = struct { |
| 7515 | }; | 7571 | }; |
| 7516 | | 7572 | |
| 7517 | const params = [_]*const llvm.Value{llvm_i32.constNull()}; | 7573 | const params = [_]*const llvm.Value{llvm_i32.constNull()}; |
| 7518 | const ptr_val = self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, ""); | 7574 | const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 7519 | const llvm_usize = try self.dg.lowerType(Type.usize); | 7575 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 7520 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); | 7576 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); |
| 7521 | } | 7577 | } |
| ... | @@ -7740,8 +7796,9 @@ pub const FuncGen = struct { | ... | @@ -7740,8 +7796,9 @@ pub const FuncGen = struct { |
| 7740 | _ = self.builder.buildStore(new_tag, union_ptr); | 7796 | _ = self.builder.buildStore(new_tag, union_ptr); |
| 7741 | return null; | 7797 | return null; |
| 7742 | } | 7798 | } |
| | 7799 | const un_llvm_ty = try self.dg.lowerType(un_ty); |
| 7743 | const tag_index = @boolToInt(layout.tag_align < layout.payload_align); | 7800 | const tag_index = @boolToInt(layout.tag_align < layout.payload_align); |
| 7744 | const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, ""); | 7801 | const tag_field_ptr = self.builder.buildStructGEP(un_llvm_ty, union_ptr, tag_index, ""); |
| 7745 | // TODO alignment on this store | 7802 | // TODO alignment on this store |
| 7746 | _ = self.builder.buildStore(new_tag, tag_field_ptr); | 7803 | _ = self.builder.buildStore(new_tag, tag_field_ptr); |
| 7747 | return null; | 7804 | return null; |
| ... | @@ -7757,12 +7814,13 @@ pub const FuncGen = struct { | ... | @@ -7757,12 +7814,13 @@ pub const FuncGen = struct { |
| 7757 | if (layout.tag_size == 0) return null; | 7814 | if (layout.tag_size == 0) return null; |
| 7758 | const union_handle = try self.resolveInst(ty_op.operand); | 7815 | const union_handle = try self.resolveInst(ty_op.operand); |
| 7759 | if (isByRef(un_ty)) { | 7816 | if (isByRef(un_ty)) { |
| | 7817 | const llvm_un_ty = try self.dg.lowerType(un_ty); |
| 7760 | if (layout.payload_size == 0) { | 7818 | if (layout.payload_size == 0) { |
| 7761 | return self.builder.buildLoad(union_handle, ""); | 7819 | return self.builder.buildLoad(llvm_un_ty, union_handle, ""); |
| 7762 | } | 7820 | } |
| 7763 | const tag_index = @boolToInt(layout.tag_align < layout.payload_align); | 7821 | const tag_index = @boolToInt(layout.tag_align < layout.payload_align); |
| 7764 | const tag_field_ptr = self.builder.buildStructGEP(union_handle, tag_index, ""); | 7822 | const tag_field_ptr = self.builder.buildStructGEP(llvm_un_ty, union_handle, tag_index, ""); |
| 7765 | return self.builder.buildLoad(tag_field_ptr, ""); | 7823 | return self.builder.buildLoad(tag_field_ptr.getGEPSourceElementType(), tag_field_ptr, ""); |
| 7766 | } else { | 7824 | } else { |
| 7767 | if (layout.payload_size == 0) { | 7825 | if (layout.payload_size == 0) { |
| 7768 | return union_handle; | 7826 | return union_handle; |
| ... | @@ -7805,7 +7863,7 @@ pub const FuncGen = struct { | ... | @@ -7805,7 +7863,7 @@ pub const FuncGen = struct { |
| 7805 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); | 7863 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 7806 | | 7864 | |
| 7807 | const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; | 7865 | const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; |
| 7808 | const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); | 7866 | const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, &params, params.len, .C, .Auto, ""); |
| 7809 | const result_ty = self.air.typeOfIndex(inst); | 7867 | const result_ty = self.air.typeOfIndex(inst); |
| 7810 | const result_llvm_ty = try self.dg.lowerType(result_ty); | 7868 | const result_llvm_ty = try self.dg.lowerType(result_ty); |
| 7811 | | 7869 | |
| ... | @@ -7832,7 +7890,7 @@ pub const FuncGen = struct { | ... | @@ -7832,7 +7890,7 @@ pub const FuncGen = struct { |
| 7832 | const operand_llvm_ty = try self.dg.lowerType(operand_ty); | 7890 | const operand_llvm_ty = try self.dg.lowerType(operand_ty); |
| 7833 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); | 7891 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 7834 | | 7892 | |
| 7835 | const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); | 7893 | const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, &params, params.len, .C, .Auto, ""); |
| 7836 | const result_ty = self.air.typeOfIndex(inst); | 7894 | const result_ty = self.air.typeOfIndex(inst); |
| 7837 | const result_llvm_ty = try self.dg.lowerType(result_ty); | 7895 | const result_llvm_ty = try self.dg.lowerType(result_ty); |
| 7838 | | 7896 | |
| ... | @@ -7889,7 +7947,7 @@ pub const FuncGen = struct { | ... | @@ -7889,7 +7947,7 @@ pub const FuncGen = struct { |
| 7889 | const params = [_]*const llvm.Value{operand}; | 7947 | const params = [_]*const llvm.Value{operand}; |
| 7890 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); | 7948 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 7891 | | 7949 | |
| 7892 | const wrong_size_result = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); | 7950 | const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, &params, params.len, .C, .Auto, ""); |
| 7893 | | 7951 | |
| 7894 | const result_ty = self.air.typeOfIndex(inst); | 7952 | const result_ty = self.air.typeOfIndex(inst); |
| 7895 | const result_llvm_ty = try self.dg.lowerType(result_ty); | 7953 | const result_llvm_ty = try self.dg.lowerType(result_ty); |
| ... | @@ -7912,7 +7970,7 @@ pub const FuncGen = struct { | ... | @@ -7912,7 +7970,7 @@ pub const FuncGen = struct { |
| 7912 | | 7970 | |
| 7913 | const llvm_fn = try self.getEnumTagNameFunction(enum_ty); | 7971 | const llvm_fn = try self.getEnumTagNameFunction(enum_ty); |
| 7914 | const params = [_]*const llvm.Value{operand}; | 7972 | const params = [_]*const llvm.Value{operand}; |
| 7915 | return self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, ""); | 7973 | return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 7916 | } | 7974 | } |
| 7917 | | 7975 | |
| 7918 | fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { | 7976 | fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { |
| ... | @@ -7973,7 +8031,8 @@ pub const FuncGen = struct { | ... | @@ -7973,7 +8031,8 @@ pub const FuncGen = struct { |
| 7973 | | 8031 | |
| 7974 | for (fields.keys()) |name, field_index| { | 8032 | for (fields.keys()) |name, field_index| { |
| 7975 | const str_init = self.dg.context.constString(name.ptr, @intCast(c_uint, name.len), .False); | 8033 | const str_init = self.dg.context.constString(name.ptr, @intCast(c_uint, name.len), .False); |
| 7976 | const str_global = self.dg.object.llvm_module.addGlobal(str_init.typeOf(), ""); | 8034 | const str_init_llvm_ty = str_init.typeOf(); |
| | 8035 | const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, ""); |
| 7977 | str_global.setInitializer(str_init); | 8036 | str_global.setInitializer(str_init); |
| 7978 | str_global.setLinkage(.Private); | 8037 | str_global.setLinkage(.Private); |
| 7979 | str_global.setGlobalConstant(.True); | 8038 | str_global.setGlobalConstant(.True); |
| ... | @@ -7981,7 +8040,7 @@ pub const FuncGen = struct { | ... | @@ -7981,7 +8040,7 @@ pub const FuncGen = struct { |
| 7981 | str_global.setAlignment(1); | 8040 | str_global.setAlignment(1); |
| 7982 | | 8041 | |
| 7983 | const slice_fields = [_]*const llvm.Value{ | 8042 | const slice_fields = [_]*const llvm.Value{ |
| 7984 | str_global.constInBoundsGEP(&array_ptr_indices, array_ptr_indices.len), | 8043 | str_init_llvm_ty.constInBoundsGEP(str_global, &array_ptr_indices, array_ptr_indices.len), |
| 7985 | usize_llvm_ty.constInt(name.len, .False), | 8044 | usize_llvm_ty.constInt(name.len, .False), |
| 7986 | }; | 8045 | }; |
| 7987 | const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); | 8046 | const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); |
| ... | @@ -8006,7 +8065,7 @@ pub const FuncGen = struct { | ... | @@ -8006,7 +8065,7 @@ pub const FuncGen = struct { |
| 8006 | switch_instr.addCase(this_tag_int_value, return_block); | 8065 | switch_instr.addCase(this_tag_int_value, return_block); |
| 8007 | | 8066 | |
| 8008 | self.builder.positionBuilderAtEnd(return_block); | 8067 | self.builder.positionBuilderAtEnd(return_block); |
| 8009 | const loaded = self.builder.buildLoad(slice_global, ""); | 8068 | const loaded = self.builder.buildLoad(llvm_ret_ty, slice_global, ""); |
| 8010 | loaded.setAlignment(slice_alignment); | 8069 | loaded.setAlignment(slice_alignment); |
| 8011 | _ = self.builder.buildRet(loaded); | 8070 | _ = self.builder.buildRet(loaded); |
| 8012 | } | 8071 | } |
| ... | @@ -8040,12 +8099,15 @@ pub const FuncGen = struct { | ... | @@ -8040,12 +8099,15 @@ pub const FuncGen = struct { |
| 8040 | | 8099 | |
| 8041 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 8100 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8042 | const operand = try self.resolveInst(un_op); | 8101 | const operand = try self.resolveInst(un_op); |
| | 8102 | const slice_ty = self.air.typeOfIndex(inst); |
| | 8103 | const slice_llvm_ty = try self.dg.lowerType(slice_ty); |
| 8043 | | 8104 | |
| 8044 | const error_name_table_ptr = try self.getErrorNameTable(); | 8105 | const error_name_table_ptr = try self.getErrorNameTable(); |
| 8045 | const error_name_table = self.builder.buildLoad(error_name_table_ptr, ""); | 8106 | const ptr_slice_llvm_ty = slice_llvm_ty.pointerType(0); |
| | 8107 | const error_name_table = self.builder.buildLoad(ptr_slice_llvm_ty, error_name_table_ptr, ""); |
| 8046 | const indices = [_]*const llvm.Value{operand}; | 8108 | const indices = [_]*const llvm.Value{operand}; |
| 8047 | const error_name_ptr = self.builder.buildInBoundsGEP(error_name_table, &indices, indices.len, ""); | 8109 | const error_name_ptr = self.builder.buildInBoundsGEP(slice_llvm_ty, error_name_table, &indices, indices.len, ""); |
| 8048 | return self.builder.buildLoad(error_name_ptr, ""); | 8110 | return self.builder.buildLoad(slice_llvm_ty, error_name_ptr, ""); |
| 8049 | } | 8111 | } |
| 8050 | | 8112 | |
| 8051 | fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 8113 | fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| ... | @@ -8222,7 +8284,7 @@ pub const FuncGen = struct { | ... | @@ -8222,7 +8284,7 @@ pub const FuncGen = struct { |
| 8222 | const llvm_elem = try self.resolveInst(elem); | 8284 | const llvm_elem = try self.resolveInst(elem); |
| 8223 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; | 8285 | const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; |
| 8224 | indices[1] = llvm_u32.constInt(llvm_i, .False); | 8286 | indices[1] = llvm_u32.constInt(llvm_i, .False); |
| 8225 | const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); | 8287 | const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 8226 | var field_ptr_payload: Type.Payload.Pointer = .{ | 8288 | var field_ptr_payload: Type.Payload.Pointer = .{ |
| 8227 | .data = .{ | 8289 | .data = .{ |
| 8228 | .pointee_type = self.air.typeOf(elem), | 8290 | .pointee_type = self.air.typeOf(elem), |
| ... | @@ -8268,7 +8330,7 @@ pub const FuncGen = struct { | ... | @@ -8268,7 +8330,7 @@ pub const FuncGen = struct { |
| 8268 | llvm_usize.constNull(), | 8330 | llvm_usize.constNull(), |
| 8269 | llvm_usize.constInt(@intCast(c_uint, i), .False), | 8331 | llvm_usize.constInt(@intCast(c_uint, i), .False), |
| 8270 | }; | 8332 | }; |
| 8271 | const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); | 8333 | const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 8272 | const llvm_elem = try self.resolveInst(elem); | 8334 | const llvm_elem = try self.resolveInst(elem); |
| 8273 | self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); | 8335 | self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); |
| 8274 | } | 8336 | } |
| ... | @@ -8277,7 +8339,7 @@ pub const FuncGen = struct { | ... | @@ -8277,7 +8339,7 @@ pub const FuncGen = struct { |
| 8277 | llvm_usize.constNull(), | 8339 | llvm_usize.constNull(), |
| 8278 | llvm_usize.constInt(@intCast(c_uint, array_info.len), .False), | 8340 | llvm_usize.constInt(@intCast(c_uint, array_info.len), .False), |
| 8279 | }; | 8341 | }; |
| 8280 | const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); | 8342 | const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); |
| 8281 | const llvm_elem = try self.dg.lowerValue(.{ | 8343 | const llvm_elem = try self.dg.lowerValue(.{ |
| 8282 | .ty = array_info.elem_type, | 8344 | .ty = array_info.elem_type, |
| 8283 | .val = sent_val, | 8345 | .val = sent_val, |
| ... | @@ -8377,7 +8439,7 @@ pub const FuncGen = struct { | ... | @@ -8377,7 +8439,7 @@ pub const FuncGen = struct { |
| 8377 | index_type.constNull(), | 8439 | index_type.constNull(), |
| 8378 | }; | 8440 | }; |
| 8379 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; | 8441 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; |
| 8380 | const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); | 8442 | const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); |
| 8381 | self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); | 8443 | self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); |
| 8382 | return result_ptr; | 8444 | return result_ptr; |
| 8383 | } | 8445 | } |
| ... | @@ -8389,7 +8451,7 @@ pub const FuncGen = struct { | ... | @@ -8389,7 +8451,7 @@ pub const FuncGen = struct { |
| 8389 | index_type.constNull(), | 8451 | index_type.constNull(), |
| 8390 | }; | 8452 | }; |
| 8391 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; | 8453 | const len: c_uint = if (field_size == layout.payload_size) 2 else 3; |
| 8392 | const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); | 8454 | const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); |
| 8393 | self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); | 8455 | self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); |
| 8394 | } | 8456 | } |
| 8395 | { | 8457 | { |
| ... | @@ -8397,7 +8459,7 @@ pub const FuncGen = struct { | ... | @@ -8397,7 +8459,7 @@ pub const FuncGen = struct { |
| 8397 | index_type.constNull(), | 8459 | index_type.constNull(), |
| 8398 | index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), | 8460 | index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), |
| 8399 | }; | 8461 | }; |
| 8400 | const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); | 8462 | const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, indices.len, ""); |
| 8401 | const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); | 8463 | const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); |
| 8402 | const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False); | 8464 | const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False); |
| 8403 | const store_inst = self.builder.buildStore(llvm_tag, field_ptr); | 8465 | const store_inst = self.builder.buildStore(llvm_tag, field_ptr); |
| ... | @@ -8464,7 +8526,7 @@ pub const FuncGen = struct { | ... | @@ -8464,7 +8526,7 @@ pub const FuncGen = struct { |
| 8464 | llvm_u32.constInt(prefetch.locality, .False), | 8526 | llvm_u32.constInt(prefetch.locality, .False), |
| 8465 | llvm_u32.constInt(@enumToInt(prefetch.cache), .False), | 8527 | llvm_u32.constInt(@enumToInt(prefetch.cache), .False), |
| 8466 | }; | 8528 | }; |
| 8467 | _ = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, ""); | 8529 | _ = self.builder.buildCall(fn_val.typeOf(), fn_val, &params, params.len, .C, .Auto, ""); |
| 8468 | return null; | 8530 | return null; |
| 8469 | } | 8531 | } |
| 8470 | | 8532 | |
| ... | @@ -8544,7 +8606,7 @@ pub const FuncGen = struct { | ... | @@ -8544,7 +8606,7 @@ pub const FuncGen = struct { |
| 8544 | }; | 8606 | }; |
| 8545 | | 8607 | |
| 8546 | var args: [1]*const llvm.Value = .{arg}; | 8608 | var args: [1]*const llvm.Value = .{arg}; |
| 8547 | const result = self.builder.buildCall(llvm_fn, &args, args.len, .C, .Auto, ""); | 8609 | const result = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .C, .Auto, ""); |
| 8548 | const final_cast_llvm_ty = final_cast orelse return result; | 8610 | const final_cast_llvm_ty = final_cast orelse return result; |
| 8549 | return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); | 8611 | return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); |
| 8550 | } | 8612 | } |
| ... | @@ -8571,22 +8633,29 @@ pub const FuncGen = struct { | ... | @@ -8571,22 +8633,29 @@ pub const FuncGen = struct { |
| 8571 | } | 8633 | } |
| 8572 | | 8634 | |
| 8573 | /// Assumes the optional is not pointer-like and payload has bits. | 8635 | /// Assumes the optional is not pointer-like and payload has bits. |
| 8574 | fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value { | 8636 | fn optIsNonNull( |
| | 8637 | self: *FuncGen, |
| | 8638 | opt_llvm_ty: *const llvm.Type, |
| | 8639 | opt_handle: *const llvm.Value, |
| | 8640 | is_by_ref: bool, |
| | 8641 | ) *const llvm.Value { |
| | 8642 | const non_null_llvm_ty = self.context.intType(8); |
| 8575 | const field = b: { | 8643 | const field = b: { |
| 8576 | if (is_by_ref) { | 8644 | if (is_by_ref) { |
| 8577 | const field_ptr = self.builder.buildStructGEP(opt_handle, 1, ""); | 8645 | const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); |
| 8578 | break :b self.builder.buildLoad(field_ptr, ""); | 8646 | break :b self.builder.buildLoad(non_null_llvm_ty, field_ptr, ""); |
| 8579 | } | 8647 | } |
| 8580 | break :b self.builder.buildExtractValue(opt_handle, 1, ""); | 8648 | break :b self.builder.buildExtractValue(opt_handle, 1, ""); |
| 8581 | }; | 8649 | }; |
| 8582 | comptime assert(optional_layout_version == 3); | 8650 | comptime assert(optional_layout_version == 3); |
| 8583 | | 8651 | |
| 8584 | return self.builder.buildICmp(.NE, field, self.context.intType(8).constInt(0, .False), ""); | 8652 | return self.builder.buildICmp(.NE, field, non_null_llvm_ty.constInt(0, .False), ""); |
| 8585 | } | 8653 | } |
| 8586 | | 8654 | |
| 8587 | /// Assumes the optional is not pointer-like and payload has bits. | 8655 | /// Assumes the optional is not pointer-like and payload has bits. |
| 8588 | fn optPayloadHandle( | 8656 | fn optPayloadHandle( |
| 8589 | fg: *FuncGen, | 8657 | fg: *FuncGen, |
| | 8658 | opt_llvm_ty: *const llvm.Type, |
| 8590 | opt_handle: *const llvm.Value, | 8659 | opt_handle: *const llvm.Value, |
| 8591 | opt_ty: Type, | 8660 | opt_ty: Type, |
| 8592 | ) *const llvm.Value { | 8661 | ) *const llvm.Value { |
| ... | @@ -8595,14 +8664,14 @@ pub const FuncGen = struct { | ... | @@ -8595,14 +8664,14 @@ pub const FuncGen = struct { |
| 8595 | | 8664 | |
| 8596 | if (isByRef(opt_ty)) { | 8665 | if (isByRef(opt_ty)) { |
| 8597 | // We have a pointer and we need to return a pointer to the first field. | 8666 | // We have a pointer and we need to return a pointer to the first field. |
| 8598 | const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, ""); | 8667 | const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, ""); |
| 8599 | | 8668 | |
| 8600 | if (isByRef(payload_ty)) { | 8669 | if (isByRef(payload_ty)) { |
| 8601 | return payload_ptr; | 8670 | return payload_ptr; |
| 8602 | } | 8671 | } |
| 8603 | const target = fg.dg.module.getTarget(); | 8672 | const target = fg.dg.module.getTarget(); |
| 8604 | const payload_alignment = payload_ty.abiAlignment(target); | 8673 | const payload_alignment = payload_ty.abiAlignment(target); |
| 8605 | const load_inst = fg.builder.buildLoad(payload_ptr, ""); | 8674 | const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); |
| 8606 | load_inst.setAlignment(payload_alignment); | 8675 | load_inst.setAlignment(payload_alignment); |
| 8607 | return load_inst; | 8676 | return load_inst; |
| 8608 | } | 8677 | } |
| ... | @@ -8627,12 +8696,12 @@ pub const FuncGen = struct { | ... | @@ -8627,12 +8696,12 @@ pub const FuncGen = struct { |
| 8627 | alloca_inst.setAlignment(payload_alignment); | 8696 | alloca_inst.setAlignment(payload_alignment); |
| 8628 | | 8697 | |
| 8629 | { | 8698 | { |
| 8630 | const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, ""); | 8699 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); |
| 8631 | const store_inst = self.builder.buildStore(payload, field_ptr); | 8700 | const store_inst = self.builder.buildStore(payload, field_ptr); |
| 8632 | store_inst.setAlignment(payload_alignment); | 8701 | store_inst.setAlignment(payload_alignment); |
| 8633 | } | 8702 | } |
| 8634 | { | 8703 | { |
| 8635 | const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, ""); | 8704 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 1, ""); |
| 8636 | const store_inst = self.builder.buildStore(non_null_field, field_ptr); | 8705 | const store_inst = self.builder.buildStore(non_null_field, field_ptr); |
| 8637 | store_inst.setAlignment(1); | 8706 | store_inst.setAlignment(1); |
| 8638 | } | 8707 | } |
| ... | @@ -8678,18 +8747,20 @@ pub const FuncGen = struct { | ... | @@ -8678,18 +8747,20 @@ pub const FuncGen = struct { |
| 8678 | if (byte_offset == 0) { | 8747 | if (byte_offset == 0) { |
| 8679 | return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); | 8748 | return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); |
| 8680 | } | 8749 | } |
| 8681 | const llvm_bytes_ptr_ty = self.context.intType(8).pointerType(0); | 8750 | const byte_llvm_ty = self.context.intType(8); |
| 8682 | const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, llvm_bytes_ptr_ty, ""); | 8751 | const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, byte_llvm_ty.pointerType(0), ""); |
| 8683 | const llvm_usize = try self.dg.lowerType(Type.usize); | 8752 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 8684 | const llvm_index = llvm_usize.constInt(byte_offset, .False); | 8753 | const llvm_index = llvm_usize.constInt(byte_offset, .False); |
| 8685 | const indices: [1]*const llvm.Value = .{llvm_index}; | 8754 | const indices: [1]*const llvm.Value = .{llvm_index}; |
| 8686 | const new_ptr = self.builder.buildInBoundsGEP(ptr_as_bytes, &indices, indices.len, ""); | 8755 | const new_ptr = self.builder.buildInBoundsGEP(byte_llvm_ty, ptr_as_bytes, &indices, indices.len, ""); |
| 8687 | return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); | 8756 | return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); |
| 8688 | }, | 8757 | }, |
| 8689 | else => { | 8758 | else => { |
| | 8759 | const struct_llvm_ty = try self.dg.lowerType(struct_ty); |
| | 8760 | |
| 8690 | var ty_buf: Type.Payload.Pointer = undefined; | 8761 | var ty_buf: Type.Payload.Pointer = undefined; |
| 8691 | if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { | 8762 | if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { |
| 8692 | return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); | 8763 | return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, ""); |
| 8693 | } else { | 8764 | } else { |
| 8694 | // If we found no index then this means this is a zero sized field at the | 8765 | // If we found no index then this means this is a zero sized field at the |
| 8695 | // end of the struct. Treat our struct pointer as an array of two and get | 8766 | // end of the struct. Treat our struct pointer as an array of two and get |
| ... | @@ -8698,7 +8769,7 @@ pub const FuncGen = struct { | ... | @@ -8698,7 +8769,7 @@ pub const FuncGen = struct { |
| 8698 | const llvm_usize = try self.dg.lowerType(Type.usize); | 8769 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 8699 | const llvm_index = llvm_usize.constInt(1, .False); | 8770 | const llvm_index = llvm_usize.constInt(1, .False); |
| 8700 | const indices: [1]*const llvm.Value = .{llvm_index}; | 8771 | const indices: [1]*const llvm.Value = .{llvm_index}; |
| 8701 | return self.builder.buildInBoundsGEP(struct_ptr, &indices, indices.len, ""); | 8772 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); |
| 8702 | } | 8773 | } |
| 8703 | }, | 8774 | }, |
| 8704 | }, | 8775 | }, |
| ... | @@ -8716,27 +8787,18 @@ pub const FuncGen = struct { | ... | @@ -8716,27 +8787,18 @@ pub const FuncGen = struct { |
| 8716 | ) !?*const llvm.Value { | 8787 | ) !?*const llvm.Value { |
| 8717 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 8788 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 8718 | const field = &union_obj.fields.values()[field_index]; | 8789 | const field = &union_obj.fields.values()[field_index]; |
| 8719 | const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); | | |
| 8720 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) { | 8790 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) { |
| 8721 | return null; | 8791 | return null; |
| 8722 | } | 8792 | } |
| 8723 | const target = self.dg.module.getTarget(); | 8793 | const target = self.dg.module.getTarget(); |
| 8724 | const layout = union_ty.unionGetLayout(target); | 8794 | const layout = union_ty.unionGetLayout(target); |
| 8725 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 8795 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 8726 | const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, ""); | 8796 | const union_llvm_ty = try self.dg.lowerType(union_ty); |
| | 8797 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); |
| | 8798 | const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); |
| 8727 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); | 8799 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); |
| 8728 | } | 8800 | } |
| 8729 | | 8801 | |
| 8730 | fn sliceElemPtr( | | |
| 8731 | self: *FuncGen, | | |
| 8732 | slice: *const llvm.Value, | | |
| 8733 | index: *const llvm.Value, | | |
| 8734 | ) *const llvm.Value { | | |
| 8735 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); | | |
| 8736 | const indices: [1]*const llvm.Value = .{index}; | | |
| 8737 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | | |
| 8738 | } | | |
| 8739 | | | |
| 8740 | fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value { | 8802 | fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value { |
| 8741 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); | 8803 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); |
| 8742 | assert(id != 0); | 8804 | assert(id != 0); |
| ... | @@ -8754,8 +8816,8 @@ pub const FuncGen = struct { | ... | @@ -8754,8 +8816,8 @@ pub const FuncGen = struct { |
| 8754 | const ptr_alignment = ptr_ty.ptrAlignment(target); | 8816 | const ptr_alignment = ptr_ty.ptrAlignment(target); |
| 8755 | const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); | 8817 | const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); |
| 8756 | if (info.host_size == 0) { | 8818 | if (info.host_size == 0) { |
| | 8819 | const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); |
| 8757 | if (isByRef(info.pointee_type)) { | 8820 | if (isByRef(info.pointee_type)) { |
| 8758 | const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); | | |
| 8759 | const result_align = info.pointee_type.abiAlignment(target); | 8821 | const result_align = info.pointee_type.abiAlignment(target); |
| 8760 | const max_align = @maximum(result_align, ptr_alignment); | 8822 | const max_align = @maximum(result_align, ptr_alignment); |
| 8761 | const result_ptr = self.buildAlloca(elem_llvm_ty); | 8823 | const result_ptr = self.buildAlloca(elem_llvm_ty); |
| ... | @@ -8773,15 +8835,15 @@ pub const FuncGen = struct { | ... | @@ -8773,15 +8835,15 @@ pub const FuncGen = struct { |
| 8773 | ); | 8835 | ); |
| 8774 | return result_ptr; | 8836 | return result_ptr; |
| 8775 | } | 8837 | } |
| 8776 | const llvm_inst = self.builder.buildLoad(ptr, ""); | 8838 | const llvm_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); |
| 8777 | llvm_inst.setAlignment(ptr_alignment); | 8839 | llvm_inst.setAlignment(ptr_alignment); |
| 8778 | llvm_inst.setVolatile(ptr_volatile); | 8840 | llvm_inst.setVolatile(ptr_volatile); |
| 8779 | return llvm_inst; | 8841 | return llvm_inst; |
| 8780 | } | 8842 | } |
| 8781 | | 8843 | |
| 8782 | const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); | 8844 | const int_elem_ty = self.context.intType(info.host_size * 8); |
| 8783 | const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); | 8845 | const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); |
| 8784 | const containing_int = self.builder.buildLoad(int_ptr, ""); | 8846 | const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); |
| 8785 | containing_int.setAlignment(ptr_alignment); | 8847 | containing_int.setAlignment(ptr_alignment); |
| 8786 | containing_int.setVolatile(ptr_volatile); | 8848 | containing_int.setVolatile(ptr_volatile); |
| 8787 | | 8849 | |
| ... | @@ -8828,9 +8890,9 @@ pub const FuncGen = struct { | ... | @@ -8828,9 +8890,9 @@ pub const FuncGen = struct { |
| 8828 | const ptr_alignment = ptr_ty.ptrAlignment(target); | 8890 | const ptr_alignment = ptr_ty.ptrAlignment(target); |
| 8829 | const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); | 8891 | const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); |
| 8830 | if (info.host_size != 0) { | 8892 | if (info.host_size != 0) { |
| 8831 | const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); | 8893 | const int_elem_ty = self.context.intType(info.host_size * 8); |
| 8832 | const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); | 8894 | const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); |
| 8833 | const containing_int = self.builder.buildLoad(int_ptr, ""); | 8895 | const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); |
| 8834 | assert(ordering == .NotAtomic); | 8896 | assert(ordering == .NotAtomic); |
| 8835 | containing_int.setAlignment(ptr_alignment); | 8897 | containing_int.setAlignment(ptr_alignment); |
| 8836 | containing_int.setVolatile(ptr_volatile); | 8898 | containing_int.setVolatile(ptr_volatile); |