| ... | @@ -929,8 +929,7 @@ pub const Object = struct { | ... | @@ -929,8 +929,7 @@ pub const Object = struct { |
| 929 | if (isByRef(param_ty)) { | 929 | if (isByRef(param_ty)) { |
| 930 | const alignment = param_ty.abiAlignment(target); | 930 | const alignment = param_ty.abiAlignment(target); |
| 931 | const param_llvm_ty = param.typeOf(); | 931 | const param_llvm_ty = param.typeOf(); |
| 932 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); | 932 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 933 | arg_ptr.setAlignment(alignment); | | |
| 934 | const store_inst = builder.buildStore(param, arg_ptr); | 933 | const store_inst = builder.buildStore(param, arg_ptr); |
| 935 | store_inst.setAlignment(alignment); | 934 | store_inst.setAlignment(alignment); |
| 936 | args.appendAssumeCapacity(arg_ptr); | 935 | args.appendAssumeCapacity(arg_ptr); |
| ... | @@ -974,8 +973,7 @@ pub const Object = struct { | ... | @@ -974,8 +973,7 @@ pub const Object = struct { |
| 974 | param_ty.abiAlignment(target), | 973 | param_ty.abiAlignment(target), |
| 975 | dg.object.target_data.abiAlignmentOfType(int_llvm_ty), | 974 | dg.object.target_data.abiAlignmentOfType(int_llvm_ty), |
| 976 | ); | 975 | ); |
| 977 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); | 976 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 978 | arg_ptr.setAlignment(alignment); | | |
| 979 | const casted_ptr = builder.buildBitCast(arg_ptr, int_ptr_llvm_ty, ""); | 977 | const casted_ptr = builder.buildBitCast(arg_ptr, int_ptr_llvm_ty, ""); |
| 980 | const store_inst = builder.buildStore(param, casted_ptr); | 978 | const store_inst = builder.buildStore(param, casted_ptr); |
| 981 | store_inst.setAlignment(alignment); | 979 | store_inst.setAlignment(alignment); |
| ... | @@ -1026,8 +1024,7 @@ pub const Object = struct { | ... | @@ -1026,8 +1024,7 @@ pub const Object = struct { |
| 1026 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 1024 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 1027 | const param_llvm_ty = try dg.lowerType(param_ty); | 1025 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 1028 | const param_alignment = param_ty.abiAlignment(target); | 1026 | const param_alignment = param_ty.abiAlignment(target); |
| 1029 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); | 1027 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| 1030 | arg_ptr.setAlignment(param_alignment); | | |
| 1031 | var field_types_buf: [8]*llvm.Type = undefined; | 1028 | var field_types_buf: [8]*llvm.Type = undefined; |
| 1032 | const field_types = field_types_buf[0..llvm_ints.len]; | 1029 | const field_types = field_types_buf[0..llvm_ints.len]; |
| 1033 | for (llvm_ints) |int_bits, i| { | 1030 | for (llvm_ints) |int_bits, i| { |
| ... | @@ -1058,8 +1055,7 @@ pub const Object = struct { | ... | @@ -1058,8 +1055,7 @@ pub const Object = struct { |
| 1058 | const param_ty = fn_info.param_types[it.zig_index - 1]; | 1055 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 1059 | const param_llvm_ty = try dg.lowerType(param_ty); | 1056 | const param_llvm_ty = try dg.lowerType(param_ty); |
| 1060 | const param_alignment = param_ty.abiAlignment(target); | 1057 | const param_alignment = param_ty.abiAlignment(target); |
| 1061 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); | 1058 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| 1062 | arg_ptr.setAlignment(param_alignment); | | |
| 1063 | var field_types_buf: [8]*llvm.Type = undefined; | 1059 | var field_types_buf: [8]*llvm.Type = undefined; |
| 1064 | const field_types = field_types_buf[0..llvm_floats.len]; | 1060 | const field_types = field_types_buf[0..llvm_floats.len]; |
| 1065 | for (llvm_floats) |float_bits, i| { | 1061 | for (llvm_floats) |float_bits, i| { |
| ... | @@ -1103,8 +1099,7 @@ pub const Object = struct { | ... | @@ -1103,8 +1099,7 @@ pub const Object = struct { |
| 1103 | llvm_arg_i += 1; | 1099 | llvm_arg_i += 1; |
| 1104 | | 1100 | |
| 1105 | const alignment = param_ty.abiAlignment(target); | 1101 | const alignment = param_ty.abiAlignment(target); |
| 1106 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); | 1102 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1107 | arg_ptr.setAlignment(alignment); | | |
| 1108 | const casted_ptr = builder.buildBitCast(arg_ptr, param.typeOf().pointerType(0), ""); | 1103 | const casted_ptr = builder.buildBitCast(arg_ptr, param.typeOf().pointerType(0), ""); |
| 1109 | _ = builder.buildStore(param, casted_ptr); | 1104 | _ = builder.buildStore(param, casted_ptr); |
| 1110 | | 1105 | |
| ... | @@ -2404,21 +2399,27 @@ pub const DeclGen = struct { | ... | @@ -2404,21 +2399,27 @@ pub const DeclGen = struct { |
| 2404 | // mismatch, because we don't have the LLVM type until the *value* is created, | 2399 | // mismatch, because we don't have the LLVM type until the *value* is created, |
| 2405 | // whereas the global needs to be created based on the type alone, because | 2400 | // whereas the global needs to be created based on the type alone, because |
| 2406 | // lowering the value may reference the global as a pointer. | 2401 | // lowering the value may reference the global as a pointer. |
| | 2402 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| | 2403 | const llvm_global_addrspace = toLlvmGlobalAddressSpace(llvm_addrspace, target); |
| 2407 | const new_global = dg.object.llvm_module.addGlobalInAddressSpace( | 2404 | const new_global = dg.object.llvm_module.addGlobalInAddressSpace( |
| 2408 | llvm_init.typeOf(), | 2405 | llvm_init.typeOf(), |
| 2409 | "", | 2406 | "", |
| 2410 | dg.llvmAddressSpace(decl.@"addrspace"), | 2407 | llvm_global_addrspace, |
| 2411 | ); | 2408 | ); |
| 2412 | new_global.setLinkage(global.getLinkage()); | 2409 | new_global.setLinkage(global.getLinkage()); |
| 2413 | new_global.setUnnamedAddr(global.getUnnamedAddress()); | 2410 | new_global.setUnnamedAddr(global.getUnnamedAddress()); |
| 2414 | new_global.setAlignment(global.getAlignment()); | 2411 | new_global.setAlignment(global.getAlignment()); |
| 2415 | if (decl.@"linksection") |section| new_global.setSection(section); | 2412 | if (decl.@"linksection") |section| new_global.setSection(section); |
| 2416 | new_global.setInitializer(llvm_init); | 2413 | new_global.setInitializer(llvm_init); |
| 2417 | // replaceAllUsesWith requires the type to be unchanged. So we bitcast | 2414 | // replaceAllUsesWith requires the type to be unchanged. So we convert |
| 2418 | // the new global to the old type and use that as the thing to replace | 2415 | // the new global to the old type and use that as the thing to replace |
| 2419 | // old uses. | 2416 | // old uses. |
| 2420 | const new_global_ptr = new_global.constBitCast(global.typeOf()); | 2417 | const new_global_ptr = if (llvm_addrspace != llvm_global_addrspace) |
| 2421 | global.replaceAllUsesWith(new_global_ptr); | 2418 | new_global.constAddrSpaceCast(llvm_init.typeOf().pointerType(llvm_addrspace)) |
| | 2419 | else |
| | 2420 | new_global; |
| | 2421 | const new_global_casted_ptr = new_global_ptr.constBitCast(global.typeOf()); |
| | 2422 | global.replaceAllUsesWith(new_global_casted_ptr); |
| 2422 | dg.object.decl_map.putAssumeCapacity(decl_index, new_global); | 2423 | dg.object.decl_map.putAssumeCapacity(decl_index, new_global); |
| 2423 | new_global.takeName(global); | 2424 | new_global.takeName(global); |
| 2424 | global.deleteGlobal(); | 2425 | global.deleteGlobal(); |
| ... | @@ -2465,7 +2466,7 @@ pub const DeclGen = struct { | ... | @@ -2465,7 +2466,7 @@ pub const DeclGen = struct { |
| 2465 | const fqn = try decl.getFullyQualifiedName(dg.module); | 2466 | const fqn = try decl.getFullyQualifiedName(dg.module); |
| 2466 | defer dg.gpa.free(fqn); | 2467 | defer dg.gpa.free(fqn); |
| 2467 | | 2468 | |
| 2468 | const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); | 2469 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| 2469 | const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace); | 2470 | const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace); |
| 2470 | gop.value_ptr.* = llvm_fn; | 2471 | gop.value_ptr.* = llvm_fn; |
| 2471 | | 2472 | |
| ... | @@ -2613,9 +2614,15 @@ pub const DeclGen = struct { | ... | @@ -2613,9 +2614,15 @@ pub const DeclGen = struct { |
| 2613 | const fqn = try decl.getFullyQualifiedName(dg.module); | 2614 | const fqn = try decl.getFullyQualifiedName(dg.module); |
| 2614 | defer dg.gpa.free(fqn); | 2615 | defer dg.gpa.free(fqn); |
| 2615 | | 2616 | |
| | 2617 | const target = dg.module.getTarget(); |
| | 2618 | |
| 2616 | const llvm_type = try dg.lowerType(decl.ty); | 2619 | const llvm_type = try dg.lowerType(decl.ty); |
| 2617 | const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); | 2620 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| 2618 | const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(llvm_type, fqn, llvm_addrspace); | 2621 | const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace( |
| | 2622 | llvm_type, |
| | 2623 | fqn, |
| | 2624 | toLlvmGlobalAddressSpace(llvm_addrspace, target), |
| | 2625 | ); |
| 2619 | gop.value_ptr.* = llvm_global; | 2626 | gop.value_ptr.* = llvm_global; |
| 2620 | | 2627 | |
| 2621 | // This is needed for declarations created by `@extern`. | 2628 | // This is needed for declarations created by `@extern`. |
| ... | @@ -2640,40 +2647,6 @@ pub const DeclGen = struct { | ... | @@ -2640,40 +2647,6 @@ pub const DeclGen = struct { |
| 2640 | return llvm_global; | 2647 | return llvm_global; |
| 2641 | } | 2648 | } |
| 2642 | | 2649 | |
| 2643 | fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint { | | |
| 2644 | const target = self.module.getTarget(); | | |
| 2645 | return switch (target.cpu.arch) { | | |
| 2646 | .i386, .x86_64 => switch (address_space) { | | |
| 2647 | .generic => llvm.address_space.default, | | |
| 2648 | .gs => llvm.address_space.x86.gs, | | |
| 2649 | .fs => llvm.address_space.x86.fs, | | |
| 2650 | .ss => llvm.address_space.x86.ss, | | |
| 2651 | else => unreachable, | | |
| 2652 | }, | | |
| 2653 | .nvptx, .nvptx64 => switch (address_space) { | | |
| 2654 | .generic => llvm.address_space.default, | | |
| 2655 | .global => llvm.address_space.nvptx.global, | | |
| 2656 | .constant => llvm.address_space.nvptx.constant, | | |
| 2657 | .param => llvm.address_space.nvptx.param, | | |
| 2658 | .shared => llvm.address_space.nvptx.shared, | | |
| 2659 | .local => llvm.address_space.nvptx.local, | | |
| 2660 | else => unreachable, | | |
| 2661 | }, | | |
| 2662 | .amdgcn => switch (address_space) { | | |
| 2663 | .generic => llvm.address_space.flat, | | |
| 2664 | .global => llvm.address_space.amdgpu.global, | | |
| 2665 | .constant => llvm.address_space.amdgpu.constant, | | |
| 2666 | .shared => llvm.address_space.amdgpu.local, | | |
| 2667 | .local => llvm.address_space.amdgpu.private, | | |
| 2668 | else => unreachable, | | |
| 2669 | }. | | |
| 2670 | else => switch (address_space) { | | |
| 2671 | .generic => llvm.address_space.default, | | |
| 2672 | else => unreachable, | | |
| 2673 | }, | | |
| 2674 | }; | | |
| 2675 | } | | |
| 2676 | | | |
| 2677 | fn isUnnamedType(dg: *DeclGen, ty: Type, val: *llvm.Value) bool { | 2650 | fn isUnnamedType(dg: *DeclGen, ty: Type, val: *llvm.Value) bool { |
| 2678 | // Once `lowerType` succeeds, successive calls to it with the same Zig type | 2651 | // Once `lowerType` succeeds, successive calls to it with the same Zig type |
| 2679 | // are guaranteed to succeed. So if a call to `lowerType` fails here it means | 2652 | // are guaranteed to succeed. So if a call to `lowerType` fails here it means |
| ... | @@ -2739,7 +2712,7 @@ pub const DeclGen = struct { | ... | @@ -2739,7 +2712,7 @@ pub const DeclGen = struct { |
| 2739 | return dg.context.structType(&fields, fields.len, .False); | 2712 | return dg.context.structType(&fields, fields.len, .False); |
| 2740 | } | 2713 | } |
| 2741 | const ptr_info = t.ptrInfo().data; | 2714 | const ptr_info = t.ptrInfo().data; |
| 2742 | const llvm_addrspace = dg.llvmAddressSpace(ptr_info.@"addrspace"); | 2715 | const llvm_addrspace = toLlvmAddressSpace(ptr_info.@"addrspace", target); |
| 2743 | if (ptr_info.host_size != 0) { | 2716 | if (ptr_info.host_size != 0) { |
| 2744 | return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace); | 2717 | return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace); |
| 2745 | } | 2718 | } |
| ... | @@ -3268,11 +3241,18 @@ pub const DeclGen = struct { | ... | @@ -3268,11 +3241,18 @@ pub const DeclGen = struct { |
| 3268 | const decl_index = tv.val.castTag(.variable).?.data.owner_decl; | 3241 | const decl_index = tv.val.castTag(.variable).?.data.owner_decl; |
| 3269 | const decl = dg.module.declPtr(decl_index); | 3242 | const decl = dg.module.declPtr(decl_index); |
| 3270 | dg.module.markDeclAlive(decl); | 3243 | dg.module.markDeclAlive(decl); |
| 3271 | const val = try dg.resolveGlobalDecl(decl_index); | | |
| 3272 | const llvm_var_type = try dg.lowerType(tv.ty); | 3244 | const llvm_var_type = try dg.lowerType(tv.ty); |
| 3273 | const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); | 3245 | const llvm_var_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| 3274 | const llvm_type = llvm_var_type.pointerType(llvm_addrspace); | 3246 | const llvm_global_addrspace = toLlvmGlobalAddressSpace(llvm_var_addrspace, target); |
| 3275 | return val.constBitCast(llvm_type); | 3247 | const llvm_var_ptr_type = llvm_var_type.pointerType(llvm_global_addrspace); |
| | 3248 | |
| | 3249 | const val = try dg.resolveGlobalDecl(decl_index); |
| | 3250 | const val_ptr = val.constBitCast(llvm_var_ptr_type); |
| | 3251 | if (llvm_global_addrspace != llvm_var_addrspace) { |
| | 3252 | const llvm_ptr_type = llvm_var_type.pointerType(llvm_var_addrspace); |
| | 3253 | return val_ptr.constAddrSpaceCast(llvm_ptr_type); |
| | 3254 | } |
| | 3255 | return val_ptr; |
| 3276 | }, | 3256 | }, |
| 3277 | .slice => { | 3257 | .slice => { |
| 3278 | const slice = tv.val.castTag(.slice).?.data; | 3258 | const slice = tv.val.castTag(.slice).?.data; |
| ... | @@ -4069,11 +4049,20 @@ pub const DeclGen = struct { | ... | @@ -4069,11 +4049,20 @@ pub const DeclGen = struct { |
| 4069 | | 4049 | |
| 4070 | self.module.markDeclAlive(decl); | 4050 | self.module.markDeclAlive(decl); |
| 4071 | | 4051 | |
| 4072 | const llvm_val = if (is_fn_body) | 4052 | const llvm_decl_val = if (is_fn_body) |
| 4073 | try self.resolveLlvmFunction(decl_index) | 4053 | try self.resolveLlvmFunction(decl_index) |
| 4074 | else | 4054 | else |
| 4075 | try self.resolveGlobalDecl(decl_index); | 4055 | try self.resolveGlobalDecl(decl_index); |
| 4076 | | 4056 | |
| | 4057 | const target = self.module.getTarget(); |
| | 4058 | const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); |
| | 4059 | const llvm_global_addrspace = toLlvmGlobalAddressSpace(llvm_addrspace, target); |
| | 4060 | const llvm_val = if (llvm_addrspace != llvm_global_addrspace) blk: { |
| | 4061 | const llvm_decl_ty = try self.lowerType(decl.ty); |
| | 4062 | const llvm_decl_ptr_ty = llvm_decl_ty.pointerType(llvm_addrspace); |
| | 4063 | break :blk llvm_decl_val.constAddrSpaceCast(llvm_decl_ptr_ty); |
| | 4064 | } else llvm_decl_val; |
| | 4065 | |
| 4077 | const llvm_type = try self.lowerType(tv.ty); | 4066 | const llvm_type = try self.lowerType(tv.ty); |
| 4078 | if (tv.ty.zigTypeTag() == .Int) { | 4067 | if (tv.ty.zigTypeTag() == .Int) { |
| 4079 | return llvm_val.constPtrToInt(llvm_type); | 4068 | return llvm_val.constPtrToInt(llvm_type); |
| ... | @@ -4339,7 +4328,9 @@ pub const FuncGen = struct { | ... | @@ -4339,7 +4328,9 @@ pub const FuncGen = struct { |
| 4339 | // We have an LLVM value but we need to create a global constant and | 4328 | // We have an LLVM value but we need to create a global constant and |
| 4340 | // set the value as its initializer, and then return a pointer to the global. | 4329 | // set the value as its initializer, and then return a pointer to the global. |
| 4341 | const target = self.dg.module.getTarget(); | 4330 | const target = self.dg.module.getTarget(); |
| 4342 | const global = self.dg.object.llvm_module.addGlobal(llvm_val.typeOf(), ""); | 4331 | const llvm_addrspace = toLlvmAddressSpace(.generic, target); |
| | 4332 | const llvm_global_addrspace = toLlvmGlobalAddressSpace(llvm_addrspace, target); |
| | 4333 | const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_global_addrspace); |
| 4343 | global.setInitializer(llvm_val); | 4334 | global.setInitializer(llvm_val); |
| 4344 | global.setLinkage(.Private); | 4335 | global.setLinkage(.Private); |
| 4345 | global.setGlobalConstant(.True); | 4336 | global.setGlobalConstant(.True); |
| ... | @@ -4349,8 +4340,10 @@ pub const FuncGen = struct { | ... | @@ -4349,8 +4340,10 @@ pub const FuncGen = struct { |
| 4349 | // the type of global constants might not match the type it is supposed to | 4340 | // the type of global constants might not match the type it is supposed to |
| 4350 | // be, and so we must bitcast the pointer at the usage sites. | 4341 | // be, and so we must bitcast the pointer at the usage sites. |
| 4351 | const wanted_llvm_ty = try self.dg.lowerType(ty); | 4342 | const wanted_llvm_ty = try self.dg.lowerType(ty); |
| 4352 | const wanted_llvm_ptr_ty = wanted_llvm_ty.pointerType(0); | 4343 | const wanted_bitcasted_llvm_ptr_ty = wanted_llvm_ty.pointerType(llvm_global_addrspace); |
| 4353 | const casted_ptr = global.constBitCast(wanted_llvm_ptr_ty); | 4344 | const bitcasted_ptr = global.constBitCast(wanted_bitcasted_llvm_ptr_ty); |
| | 4345 | const wanted_llvm_ptr_ty = wanted_llvm_ty.pointerType(llvm_addrspace); |
| | 4346 | const casted_ptr = bitcasted_ptr.constAddrSpaceCast(wanted_llvm_ptr_ty); |
| 4354 | gop.value_ptr.* = casted_ptr; | 4347 | gop.value_ptr.* = casted_ptr; |
| 4355 | return casted_ptr; | 4348 | return casted_ptr; |
| 4356 | } | 4349 | } |
| ... | @@ -4606,8 +4599,7 @@ pub const FuncGen = struct { | ... | @@ -4606,8 +4599,7 @@ pub const FuncGen = struct { |
| 4606 | | 4599 | |
| 4607 | const ret_ptr = if (!sret) null else blk: { | 4600 | const ret_ptr = if (!sret) null else blk: { |
| 4608 | const llvm_ret_ty = try self.dg.lowerType(return_type); | 4601 | const llvm_ret_ty = try self.dg.lowerType(return_type); |
| 4609 | const ret_ptr = self.buildAlloca(llvm_ret_ty); | 4602 | const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(target)); |
| 4610 | ret_ptr.setAlignment(return_type.abiAlignment(target)); | | |
| 4611 | try llvm_args.append(ret_ptr); | 4603 | try llvm_args.append(ret_ptr); |
| 4612 | break :blk ret_ptr; | 4604 | break :blk ret_ptr; |
| 4613 | }; | 4605 | }; |
| ... | @@ -4654,8 +4646,7 @@ pub const FuncGen = struct { | ... | @@ -4654,8 +4646,7 @@ pub const FuncGen = struct { |
| 4654 | } else { | 4646 | } else { |
| 4655 | const alignment = param_ty.abiAlignment(target); | 4647 | const alignment = param_ty.abiAlignment(target); |
| 4656 | const param_llvm_ty = llvm_arg.typeOf(); | 4648 | const param_llvm_ty = llvm_arg.typeOf(); |
| 4657 | const arg_ptr = self.buildAlloca(param_llvm_ty); | 4649 | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); |
| 4658 | arg_ptr.setAlignment(alignment); | | |
| 4659 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); | 4650 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); |
| 4660 | store_inst.setAlignment(alignment); | 4651 | store_inst.setAlignment(alignment); |
| 4661 | try llvm_args.append(arg_ptr); | 4652 | try llvm_args.append(arg_ptr); |
| ... | @@ -4682,8 +4673,7 @@ pub const FuncGen = struct { | ... | @@ -4682,8 +4673,7 @@ pub const FuncGen = struct { |
| 4682 | param_ty.abiAlignment(target), | 4673 | param_ty.abiAlignment(target), |
| 4683 | self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty), | 4674 | self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty), |
| 4684 | ); | 4675 | ); |
| 4685 | const int_ptr = self.buildAlloca(int_llvm_ty); | 4676 | const int_ptr = self.buildAlloca(int_llvm_ty, alignment); |
| 4686 | int_ptr.setAlignment(alignment); | | |
| 4687 | const param_llvm_ty = try self.dg.lowerType(param_ty); | 4677 | const param_llvm_ty = try self.dg.lowerType(param_ty); |
| 4688 | const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); | 4678 | const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); |
| 4689 | const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); | 4679 | const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); |
| ... | @@ -4709,7 +4699,7 @@ pub const FuncGen = struct { | ... | @@ -4709,7 +4699,7 @@ pub const FuncGen = struct { |
| 4709 | const llvm_arg = try self.resolveInst(arg); | 4699 | const llvm_arg = try self.resolveInst(arg); |
| 4710 | const is_by_ref = isByRef(param_ty); | 4700 | const is_by_ref = isByRef(param_ty); |
| 4711 | const arg_ptr = if (is_by_ref) llvm_arg else p: { | 4701 | const arg_ptr = if (is_by_ref) llvm_arg else p: { |
| 4712 | const p = self.buildAlloca(llvm_arg.typeOf()); | 4702 | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 4713 | const store_inst = self.builder.buildStore(llvm_arg, p); | 4703 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 4714 | store_inst.setAlignment(param_ty.abiAlignment(target)); | 4704 | store_inst.setAlignment(param_ty.abiAlignment(target)); |
| 4715 | break :p p; | 4705 | break :p p; |
| ... | @@ -4738,7 +4728,7 @@ pub const FuncGen = struct { | ... | @@ -4738,7 +4728,7 @@ pub const FuncGen = struct { |
| 4738 | const llvm_arg = try self.resolveInst(arg); | 4728 | const llvm_arg = try self.resolveInst(arg); |
| 4739 | const is_by_ref = isByRef(param_ty); | 4729 | const is_by_ref = isByRef(param_ty); |
| 4740 | const arg_ptr = if (is_by_ref) llvm_arg else p: { | 4730 | const arg_ptr = if (is_by_ref) llvm_arg else p: { |
| 4741 | const p = self.buildAlloca(llvm_arg.typeOf()); | 4731 | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 4742 | const store_inst = self.builder.buildStore(llvm_arg, p); | 4732 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 4743 | store_inst.setAlignment(param_ty.abiAlignment(target)); | 4733 | store_inst.setAlignment(param_ty.abiAlignment(target)); |
| 4744 | break :p p; | 4734 | break :p p; |
| ... | @@ -4775,7 +4765,7 @@ pub const FuncGen = struct { | ... | @@ -4775,7 +4765,7 @@ pub const FuncGen = struct { |
| 4775 | const arg_ty = self.air.typeOf(arg); | 4765 | const arg_ty = self.air.typeOf(arg); |
| 4776 | var llvm_arg = try self.resolveInst(arg); | 4766 | var llvm_arg = try self.resolveInst(arg); |
| 4777 | if (!isByRef(arg_ty)) { | 4767 | if (!isByRef(arg_ty)) { |
| 4778 | const p = self.buildAlloca(llvm_arg.typeOf()); | 4768 | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 4779 | const store_inst = self.builder.buildStore(llvm_arg, p); | 4769 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 4780 | store_inst.setAlignment(arg_ty.abiAlignment(target)); | 4770 | store_inst.setAlignment(arg_ty.abiAlignment(target)); |
| 4781 | llvm_arg = store_inst; | 4771 | llvm_arg = store_inst; |
| ... | @@ -4832,9 +4822,8 @@ pub const FuncGen = struct { | ... | @@ -4832,9 +4822,8 @@ pub const FuncGen = struct { |
| 4832 | // In this case the function return type is honoring the calling convention by having | 4822 | // In this case the function return type is honoring the calling convention by having |
| 4833 | // a different LLVM type than the usual one. We solve this here at the callsite | 4823 | // a different LLVM type than the usual one. We solve this here at the callsite |
| 4834 | // by bitcasting a pointer to our canonical type, then loading it if necessary. | 4824 | // by bitcasting a pointer to our canonical type, then loading it if necessary. |
| 4835 | const rp = self.buildAlloca(llvm_ret_ty); | | |
| 4836 | const alignment = return_type.abiAlignment(target); | 4825 | const alignment = return_type.abiAlignment(target); |
| 4837 | rp.setAlignment(alignment); | 4826 | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 4838 | const ptr_abi_ty = abi_ret_ty.pointerType(0); | 4827 | const ptr_abi_ty = abi_ret_ty.pointerType(0); |
| 4839 | const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); | 4828 | const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); |
| 4840 | const store_inst = self.builder.buildStore(call, casted_ptr); | 4829 | const store_inst = self.builder.buildStore(call, casted_ptr); |
| ... | @@ -4851,9 +4840,8 @@ pub const FuncGen = struct { | ... | @@ -4851,9 +4840,8 @@ pub const FuncGen = struct { |
| 4851 | if (isByRef(return_type)) { | 4840 | if (isByRef(return_type)) { |
| 4852 | // our by-ref status disagrees with sret so we must allocate, store, | 4841 | // our by-ref status disagrees with sret so we must allocate, store, |
| 4853 | // and return the allocation pointer. | 4842 | // and return the allocation pointer. |
| 4854 | const rp = self.buildAlloca(llvm_ret_ty); | | |
| 4855 | const alignment = return_type.abiAlignment(target); | 4843 | const alignment = return_type.abiAlignment(target); |
| 4856 | rp.setAlignment(alignment); | 4844 | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 4857 | const store_inst = self.builder.buildStore(call, rp); | 4845 | const store_inst = self.builder.buildStore(call, rp); |
| 4858 | store_inst.setAlignment(alignment); | 4846 | store_inst.setAlignment(alignment); |
| 4859 | return rp; | 4847 | return rp; |
| ... | @@ -4912,8 +4900,7 @@ pub const FuncGen = struct { | ... | @@ -4912,8 +4900,7 @@ pub const FuncGen = struct { |
| 4912 | return null; | 4900 | return null; |
| 4913 | } | 4901 | } |
| 4914 | | 4902 | |
| 4915 | const rp = self.buildAlloca(llvm_ret_ty); | 4903 | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 4916 | rp.setAlignment(alignment); | | |
| 4917 | const store_inst = self.builder.buildStore(operand, rp); | 4904 | const store_inst = self.builder.buildStore(operand, rp); |
| 4918 | store_inst.setAlignment(alignment); | 4905 | store_inst.setAlignment(alignment); |
| 4919 | const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); | 4906 | const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); |
| ... | @@ -6031,8 +6018,7 @@ pub const FuncGen = struct { | ... | @@ -6031,8 +6018,7 @@ pub const FuncGen = struct { |
| 6031 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); | 6018 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| 6032 | } else { | 6019 | } else { |
| 6033 | const alignment = arg_ty.abiAlignment(target); | 6020 | const alignment = arg_ty.abiAlignment(target); |
| 6034 | const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf()); | 6021 | const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment); |
| 6035 | arg_ptr.setAlignment(alignment); | | |
| 6036 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); | 6022 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); |
| 6037 | store_inst.setAlignment(alignment); | 6023 | store_inst.setAlignment(alignment); |
| 6038 | llvm_param_values[llvm_param_i] = arg_ptr; | 6024 | llvm_param_values[llvm_param_i] = arg_ptr; |
| ... | @@ -6533,8 +6519,7 @@ pub const FuncGen = struct { | ... | @@ -6533,8 +6519,7 @@ pub const FuncGen = struct { |
| 6533 | const llvm_optional_ty = try self.dg.lowerType(optional_ty); | 6519 | const llvm_optional_ty = try self.dg.lowerType(optional_ty); |
| 6534 | if (isByRef(optional_ty)) { | 6520 | if (isByRef(optional_ty)) { |
| 6535 | const target = self.dg.module.getTarget(); | 6521 | const target = self.dg.module.getTarget(); |
| 6536 | const optional_ptr = self.buildAlloca(llvm_optional_ty); | 6522 | const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(target)); |
| 6537 | optional_ptr.setAlignment(optional_ty.abiAlignment(target)); | | |
| 6538 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); | 6523 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); |
| 6539 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 6524 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 6540 | .base = .{ .tag = .single_mut_pointer }, | 6525 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -6567,8 +6552,7 @@ pub const FuncGen = struct { | ... | @@ -6567,8 +6552,7 @@ pub const FuncGen = struct { |
| 6567 | const payload_offset = errUnionPayloadOffset(payload_ty, target); | 6552 | const payload_offset = errUnionPayloadOffset(payload_ty, target); |
| 6568 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6553 | const error_offset = errUnionErrorOffset(payload_ty, target); |
| 6569 | if (isByRef(err_un_ty)) { | 6554 | if (isByRef(err_un_ty)) { |
| 6570 | const result_ptr = self.buildAlloca(err_un_llvm_ty); | 6555 | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target)); |
| 6571 | result_ptr.setAlignment(err_un_ty.abiAlignment(target)); | | |
| 6572 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); | 6556 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 6573 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); | 6557 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); |
| 6574 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6558 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); |
| ... | @@ -6602,8 +6586,7 @@ pub const FuncGen = struct { | ... | @@ -6602,8 +6586,7 @@ pub const FuncGen = struct { |
| 6602 | const payload_offset = errUnionPayloadOffset(payload_ty, target); | 6586 | const payload_offset = errUnionPayloadOffset(payload_ty, target); |
| 6603 | const error_offset = errUnionErrorOffset(payload_ty, target); | 6587 | const error_offset = errUnionErrorOffset(payload_ty, target); |
| 6604 | if (isByRef(err_un_ty)) { | 6588 | if (isByRef(err_un_ty)) { |
| 6605 | const result_ptr = self.buildAlloca(err_un_llvm_ty); | 6589 | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target)); |
| 6606 | result_ptr.setAlignment(err_un_ty.abiAlignment(target)); | | |
| 6607 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); | 6590 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 6608 | const store_inst = self.builder.buildStore(operand, err_ptr); | 6591 | const store_inst = self.builder.buildStore(operand, err_ptr); |
| 6609 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); | 6592 | store_inst.setAlignment(Type.anyerror.abiAlignment(target)); |
| ... | @@ -7021,9 +7004,8 @@ pub const FuncGen = struct { | ... | @@ -7021,9 +7004,8 @@ pub const FuncGen = struct { |
| 7021 | | 7004 | |
| 7022 | if (isByRef(dest_ty)) { | 7005 | if (isByRef(dest_ty)) { |
| 7023 | const target = self.dg.module.getTarget(); | 7006 | const target = self.dg.module.getTarget(); |
| 7024 | const alloca_inst = self.buildAlloca(llvm_dest_ty); | | |
| 7025 | const result_alignment = dest_ty.abiAlignment(target); | 7007 | const result_alignment = dest_ty.abiAlignment(target); |
| 7026 | alloca_inst.setAlignment(result_alignment); | 7008 | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); |
| 7027 | { | 7009 | { |
| 7028 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); | 7010 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 7029 | const store_inst = self.builder.buildStore(result, field_ptr); | 7011 | const store_inst = self.builder.buildStore(result, field_ptr); |
| ... | @@ -7373,9 +7355,8 @@ pub const FuncGen = struct { | ... | @@ -7373,9 +7355,8 @@ pub const FuncGen = struct { |
| 7373 | | 7355 | |
| 7374 | if (isByRef(dest_ty)) { | 7356 | if (isByRef(dest_ty)) { |
| 7375 | const target = self.dg.module.getTarget(); | 7357 | const target = self.dg.module.getTarget(); |
| 7376 | const alloca_inst = self.buildAlloca(llvm_dest_ty); | | |
| 7377 | const result_alignment = dest_ty.abiAlignment(target); | 7358 | const result_alignment = dest_ty.abiAlignment(target); |
| 7378 | alloca_inst.setAlignment(result_alignment); | 7359 | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); |
| 7379 | { | 7360 | { |
| 7380 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); | 7361 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 7381 | const store_inst = self.builder.buildStore(result, field_ptr); | 7362 | const store_inst = self.builder.buildStore(result, field_ptr); |
| ... | @@ -7653,7 +7634,7 @@ pub const FuncGen = struct { | ... | @@ -7653,7 +7634,7 @@ pub const FuncGen = struct { |
| 7653 | if (!result_is_ref) { | 7634 | if (!result_is_ref) { |
| 7654 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); | 7635 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); |
| 7655 | } | 7636 | } |
| 7656 | const array_ptr = self.buildAlloca(llvm_dest_ty); | 7637 | const array_ptr = self.buildAlloca(llvm_dest_ty, null); |
| 7657 | const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8; | 7638 | const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8; |
| 7658 | if (bitcast_ok) { | 7639 | if (bitcast_ok) { |
| 7659 | const llvm_vector_ty = try self.dg.lowerType(operand_ty); | 7640 | const llvm_vector_ty = try self.dg.lowerType(operand_ty); |
| ... | @@ -7729,8 +7710,7 @@ pub const FuncGen = struct { | ... | @@ -7729,8 +7710,7 @@ pub const FuncGen = struct { |
| 7729 | if (result_is_ref) { | 7710 | if (result_is_ref) { |
| 7730 | // Bitcast the result pointer, then store. | 7711 | // Bitcast the result pointer, then store. |
| 7731 | const alignment = @maximum(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target)); | 7712 | const alignment = @maximum(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target)); |
| 7732 | const result_ptr = self.buildAlloca(llvm_dest_ty); | 7713 | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); |
| 7733 | result_ptr.setAlignment(alignment); | | |
| 7734 | const operand_llvm_ty = try self.dg.lowerType(operand_ty); | 7714 | const operand_llvm_ty = try self.dg.lowerType(operand_ty); |
| 7735 | const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); | 7715 | const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); |
| 7736 | const store_inst = self.builder.buildStore(operand, casted_ptr); | 7716 | const store_inst = self.builder.buildStore(operand, casted_ptr); |
| ... | @@ -7743,8 +7723,7 @@ pub const FuncGen = struct { | ... | @@ -7743,8 +7723,7 @@ pub const FuncGen = struct { |
| 7743 | // but LLVM won't let us bitcast struct values. | 7723 | // but LLVM won't let us bitcast struct values. |
| 7744 | // Therefore, we store operand to bitcasted alloca, then load for result. | 7724 | // Therefore, we store operand to bitcasted alloca, then load for result. |
| 7745 | const alignment = @maximum(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target)); | 7725 | const alignment = @maximum(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target)); |
| 7746 | const result_ptr = self.buildAlloca(llvm_dest_ty); | 7726 | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); |
| 7747 | result_ptr.setAlignment(alignment); | | |
| 7748 | const operand_llvm_ty = try self.dg.lowerType(operand_ty); | 7727 | const operand_llvm_ty = try self.dg.lowerType(operand_ty); |
| 7749 | const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); | 7728 | const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); |
| 7750 | const store_inst = self.builder.buildStore(operand, casted_ptr); | 7729 | const store_inst = self.builder.buildStore(operand, casted_ptr); |
| ... | @@ -7820,11 +7799,9 @@ pub const FuncGen = struct { | ... | @@ -7820,11 +7799,9 @@ pub const FuncGen = struct { |
| 7820 | if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty); | 7799 | if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty); |
| 7821 | | 7800 | |
| 7822 | const pointee_llvm_ty = try self.dg.lowerType(pointee_type); | 7801 | const pointee_llvm_ty = try self.dg.lowerType(pointee_type); |
| 7823 | const alloca_inst = self.buildAlloca(pointee_llvm_ty); | | |
| 7824 | const target = self.dg.module.getTarget(); | 7802 | const target = self.dg.module.getTarget(); |
| 7825 | const alignment = ptr_ty.ptrAlignment(target); | 7803 | const alignment = ptr_ty.ptrAlignment(target); |
| 7826 | alloca_inst.setAlignment(alignment); | 7804 | return self.buildAlloca(pointee_llvm_ty, alignment); |
| 7827 | return alloca_inst; | | |
| 7828 | } | 7805 | } |
| 7829 | | 7806 | |
| 7830 | fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7807 | fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| ... | @@ -7835,15 +7812,13 @@ pub const FuncGen = struct { | ... | @@ -7835,15 +7812,13 @@ pub const FuncGen = struct { |
| 7835 | if (self.ret_ptr) |ret_ptr| return ret_ptr; | 7812 | if (self.ret_ptr) |ret_ptr| return ret_ptr; |
| 7836 | const ret_llvm_ty = try self.dg.lowerType(ret_ty); | 7813 | const ret_llvm_ty = try self.dg.lowerType(ret_ty); |
| 7837 | const target = self.dg.module.getTarget(); | 7814 | const target = self.dg.module.getTarget(); |
| 7838 | const alloca_inst = self.buildAlloca(ret_llvm_ty); | 7815 | return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(target)); |
| 7839 | alloca_inst.setAlignment(ptr_ty.ptrAlignment(target)); | | |
| 7840 | return alloca_inst; | | |
| 7841 | } | 7816 | } |
| 7842 | | 7817 | |
| 7843 | /// Use this instead of builder.buildAlloca, because this function makes sure to | 7818 | /// Use this instead of builder.buildAlloca, because this function makes sure to |
| 7844 | /// put the alloca instruction at the top of the function! | 7819 | /// put the alloca instruction at the top of the function! |
| 7845 | fn buildAlloca(self: *FuncGen, llvm_ty: *llvm.Type) *llvm.Value { | 7820 | fn buildAlloca(self: *FuncGen, llvm_ty: *llvm.Type, alignment: ?c_uint) *llvm.Value { |
| 7846 | return buildAllocaInner(self.builder, self.llvm_func, self.di_scope != null, llvm_ty); | 7821 | return buildAllocaInner(self.builder, self.llvm_func, self.di_scope != null, llvm_ty, alignment, self.dg.module.getTarget()); |
| 7847 | } | 7822 | } |
| 7848 | | 7823 | |
| 7849 | fn airStore(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7824 | fn airStore(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| ... | @@ -8801,10 +8776,9 @@ pub const FuncGen = struct { | ... | @@ -8801,10 +8776,9 @@ pub const FuncGen = struct { |
| 8801 | | 8776 | |
| 8802 | if (isByRef(result_ty)) { | 8777 | if (isByRef(result_ty)) { |
| 8803 | const llvm_u32 = self.context.intType(32); | 8778 | const llvm_u32 = self.context.intType(32); |
| 8804 | const alloca_inst = self.buildAlloca(llvm_result_ty); | | |
| 8805 | // TODO in debug builds init to undef so that the padding will be 0xaa | 8779 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 8806 | // even if we fully populate the fields. | 8780 | // even if we fully populate the fields. |
| 8807 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); | 8781 | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(target)); |
| 8808 | | 8782 | |
| 8809 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; | 8783 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| 8810 | for (elements) |elem, i| { | 8784 | for (elements) |elem, i| { |
| ... | @@ -8842,8 +8816,7 @@ pub const FuncGen = struct { | ... | @@ -8842,8 +8816,7 @@ pub const FuncGen = struct { |
| 8842 | assert(isByRef(result_ty)); | 8816 | assert(isByRef(result_ty)); |
| 8843 | | 8817 | |
| 8844 | const llvm_usize = try self.dg.lowerType(Type.usize); | 8818 | const llvm_usize = try self.dg.lowerType(Type.usize); |
| 8845 | const alloca_inst = self.buildAlloca(llvm_result_ty); | 8819 | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(target)); |
| 8846 | alloca_inst.setAlignment(result_ty.abiAlignment(target)); | | |
| 8847 | | 8820 | |
| 8848 | const array_info = result_ty.arrayInfo(); | 8821 | const array_info = result_ty.arrayInfo(); |
| 8849 | var elem_ptr_payload: Type.Payload.Pointer = .{ | 8822 | var elem_ptr_payload: Type.Payload.Pointer = .{ |
| ... | @@ -8918,7 +8891,7 @@ pub const FuncGen = struct { | ... | @@ -8918,7 +8891,7 @@ pub const FuncGen = struct { |
| 8918 | // necessarily match the format that we need, depending on which tag is active. We | 8891 | // necessarily match the format that we need, depending on which tag is active. We |
| 8919 | // must construct the correct unnamed struct type here and bitcast, in order to | 8892 | // must construct the correct unnamed struct type here and bitcast, in order to |
| 8920 | // then set the fields appropriately. | 8893 | // then set the fields appropriately. |
| 8921 | const result_ptr = self.buildAlloca(union_llvm_ty); | 8894 | const result_ptr = self.buildAlloca(union_llvm_ty, null); |
| 8922 | const llvm_payload = try self.resolveInst(extra.init); | 8895 | const llvm_payload = try self.resolveInst(extra.init); |
| 8923 | assert(union_obj.haveFieldTypes()); | 8896 | assert(union_obj.haveFieldTypes()); |
| 8924 | const field = union_obj.fields.values()[extra.field_index]; | 8897 | const field = union_obj.fields.values()[extra.field_index]; |
| ... | @@ -9234,9 +9207,8 @@ pub const FuncGen = struct { | ... | @@ -9234,9 +9207,8 @@ pub const FuncGen = struct { |
| 9234 | | 9207 | |
| 9235 | if (isByRef(optional_ty)) { | 9208 | if (isByRef(optional_ty)) { |
| 9236 | const target = self.dg.module.getTarget(); | 9209 | const target = self.dg.module.getTarget(); |
| 9237 | const alloca_inst = self.buildAlloca(optional_llvm_ty); | | |
| 9238 | const payload_alignment = optional_ty.abiAlignment(target); | 9210 | const payload_alignment = optional_ty.abiAlignment(target); |
| 9239 | alloca_inst.setAlignment(payload_alignment); | 9211 | const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment); |
| 9240 | | 9212 | |
| 9241 | { | 9213 | { |
| 9242 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); | 9214 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); |
| ... | @@ -9360,8 +9332,7 @@ pub const FuncGen = struct { | ... | @@ -9360,8 +9332,7 @@ pub const FuncGen = struct { |
| 9360 | if (isByRef(info.pointee_type)) { | 9332 | if (isByRef(info.pointee_type)) { |
| 9361 | const result_align = info.pointee_type.abiAlignment(target); | 9333 | const result_align = info.pointee_type.abiAlignment(target); |
| 9362 | const max_align = @maximum(result_align, ptr_alignment); | 9334 | const max_align = @maximum(result_align, ptr_alignment); |
| 9363 | const result_ptr = self.buildAlloca(elem_llvm_ty); | 9335 | const result_ptr = self.buildAlloca(elem_llvm_ty, max_align); |
| 9364 | result_ptr.setAlignment(max_align); | | |
| 9365 | const llvm_ptr_u8 = self.context.intType(8).pointerType(0); | 9336 | const llvm_ptr_u8 = self.context.intType(8).pointerType(0); |
| 9366 | const llvm_usize = self.context.intType(Type.usize.intInfo(target).bits); | 9337 | const llvm_usize = self.context.intType(Type.usize.intInfo(target).bits); |
| 9367 | const size_bytes = info.pointee_type.abiSize(target); | 9338 | const size_bytes = info.pointee_type.abiSize(target); |
| ... | @@ -9394,8 +9365,7 @@ pub const FuncGen = struct { | ... | @@ -9394,8 +9365,7 @@ pub const FuncGen = struct { |
| 9394 | | 9365 | |
| 9395 | if (isByRef(info.pointee_type)) { | 9366 | if (isByRef(info.pointee_type)) { |
| 9396 | const result_align = info.pointee_type.abiAlignment(target); | 9367 | const result_align = info.pointee_type.abiAlignment(target); |
| 9397 | const result_ptr = self.buildAlloca(elem_llvm_ty); | 9368 | const result_ptr = self.buildAlloca(elem_llvm_ty, result_align); |
| 9398 | result_ptr.setAlignment(result_align); | | |
| 9399 | | 9369 | |
| 9400 | const same_size_int = self.context.intType(elem_bits); | 9370 | const same_size_int = self.context.intType(elem_bits); |
| 9401 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 9371 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| ... | @@ -9519,8 +9489,7 @@ pub const FuncGen = struct { | ... | @@ -9519,8 +9489,7 @@ pub const FuncGen = struct { |
| 9519 | .x86_64 => { | 9489 | .x86_64 => { |
| 9520 | const array_llvm_ty = usize_llvm_ty.arrayType(6); | 9490 | const array_llvm_ty = usize_llvm_ty.arrayType(6); |
| 9521 | const array_ptr = fg.valgrind_client_request_array orelse a: { | 9491 | const array_ptr = fg.valgrind_client_request_array orelse a: { |
| 9522 | const array_ptr = fg.buildAlloca(array_llvm_ty); | 9492 | const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment); |
| 9523 | array_ptr.setAlignment(usize_alignment); | | |
| 9524 | fg.valgrind_client_request_array = array_ptr; | 9493 | fg.valgrind_client_request_array = array_ptr; |
| 9525 | break :a array_ptr; | 9494 | break :a array_ptr; |
| 9526 | }; | 9495 | }; |
| ... | @@ -9822,6 +9791,74 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca | ... | @@ -9822,6 +9791,74 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca |
| 9822 | }; | 9791 | }; |
| 9823 | } | 9792 | } |
| 9824 | | 9793 | |
| | 9794 | /// Convert a zig-address space to an llvm address space. |
| | 9795 | fn toLlvmAddressSpace(address_space: std.builtin.AddressSpace, target: std.Target) c_uint { |
| | 9796 | return switch (target.cpu.arch) { |
| | 9797 | .i386, .x86_64 => switch (address_space) { |
| | 9798 | .generic => llvm.address_space.default, |
| | 9799 | .gs => llvm.address_space.x86.gs, |
| | 9800 | .fs => llvm.address_space.x86.fs, |
| | 9801 | .ss => llvm.address_space.x86.ss, |
| | 9802 | else => unreachable, |
| | 9803 | }, |
| | 9804 | .nvptx, .nvptx64 => switch (address_space) { |
| | 9805 | .generic => llvm.address_space.default, |
| | 9806 | .global => llvm.address_space.nvptx.global, |
| | 9807 | .constant => llvm.address_space.nvptx.constant, |
| | 9808 | .param => llvm.address_space.nvptx.param, |
| | 9809 | .shared => llvm.address_space.nvptx.shared, |
| | 9810 | .local => llvm.address_space.nvptx.local, |
| | 9811 | else => unreachable, |
| | 9812 | }, |
| | 9813 | .amdgcn => switch (address_space) { |
| | 9814 | .generic => llvm.address_space.amdgpu.flat, |
| | 9815 | .global => llvm.address_space.amdgpu.global, |
| | 9816 | .constant => llvm.address_space.amdgpu.constant, |
| | 9817 | .shared => llvm.address_space.amdgpu.local, |
| | 9818 | .local => llvm.address_space.amdgpu.private, |
| | 9819 | else => unreachable, |
| | 9820 | }, |
| | 9821 | else => switch (address_space) { |
| | 9822 | .generic => llvm.address_space.default, |
| | 9823 | else => unreachable, |
| | 9824 | }, |
| | 9825 | }; |
| | 9826 | } |
| | 9827 | |
| | 9828 | /// On some targets, local values that are in the generic address space must be generated into a |
| | 9829 | /// different address, space and then cast back to the generic address space. |
| | 9830 | /// For example, on GPUs local variable declarations must be generated into the local address space. |
| | 9831 | /// This function returns the address space local values should be generated into. |
| | 9832 | fn llvmAllocaAddressSpace(target: std.Target) c_uint { |
| | 9833 | return switch (target.cpu.arch) { |
| | 9834 | // On amdgcn, locals should be generated into the private address space. |
| | 9835 | // To make Zig not impossible to use, these are then converted to addresses in the |
| | 9836 | // generic address space and treates as regular pointers. This is the way that HIP also does it. |
| | 9837 | .amdgcn => llvm.address_space.amdgpu.private, |
| | 9838 | else => llvm.address_space.default, |
| | 9839 | }; |
| | 9840 | } |
| | 9841 | |
| | 9842 | /// On some targets, global values that are in the generic address space must be generated into a |
| | 9843 | /// different address space, and then cast back to the generic address space. |
| | 9844 | fn llvmDefaultGlobalAddressSpace(target: std.Target) c_uint { |
| | 9845 | return switch (target.cpu.arch) { |
| | 9846 | // On amdgcn, globals must be explicitly allocated and uploaded so that the program can access |
| | 9847 | // them. |
| | 9848 | .amdgcn => llvm.address_space.amdgpu.global, |
| | 9849 | else => llvm.address_space.default, |
| | 9850 | }; |
| | 9851 | } |
| | 9852 | |
| | 9853 | /// If `llvm_addrspace` is generic, convert it to the actual address space that globals |
| | 9854 | /// should be stored in by default. |
| | 9855 | fn toLlvmGlobalAddressSpace(llvm_addrspace: c_uint, target: std.Target) c_uint { |
| | 9856 | return if (llvm_addrspace == llvm.address_space.default) |
| | 9857 | llvmDefaultGlobalAddressSpace(target) |
| | 9858 | else |
| | 9859 | llvm_addrspace; |
| | 9860 | } |
| | 9861 | |
| 9825 | /// Take into account 0 bit fields and padding. Returns null if an llvm | 9862 | /// Take into account 0 bit fields and padding. Returns null if an llvm |
| 9826 | /// field could not be found. | 9863 | /// field could not be found. |
| 9827 | /// This only happens if you want the field index of a zero sized field at | 9864 | /// This only happens if you want the field index of a zero sized field at |
| ... | @@ -10523,25 +10560,43 @@ fn buildAllocaInner( | ... | @@ -10523,25 +10560,43 @@ fn buildAllocaInner( |
| 10523 | llvm_func: *llvm.Value, | 10560 | llvm_func: *llvm.Value, |
| 10524 | di_scope_non_null: bool, | 10561 | di_scope_non_null: bool, |
| 10525 | llvm_ty: *llvm.Type, | 10562 | llvm_ty: *llvm.Type, |
| | 10563 | maybe_alignment: ?c_uint, |
| | 10564 | target: std.Target, |
| 10526 | ) *llvm.Value { | 10565 | ) *llvm.Value { |
| 10527 | const prev_block = builder.getInsertBlock(); | 10566 | const address_space = llvmAllocaAddressSpace(target); |
| 10528 | const prev_debug_location = builder.getCurrentDebugLocation2(); | 10567 | |
| 10529 | defer { | 10568 | const alloca = blk: { |
| 10530 | builder.positionBuilderAtEnd(prev_block); | 10569 | const prev_block = builder.getInsertBlock(); |
| 10531 | if (di_scope_non_null) { | 10570 | const prev_debug_location = builder.getCurrentDebugLocation2(); |
| 10532 | builder.setCurrentDebugLocation2(prev_debug_location); | 10571 | defer { |
| | 10572 | builder.positionBuilderAtEnd(prev_block); |
| | 10573 | if (di_scope_non_null) { |
| | 10574 | builder.setCurrentDebugLocation2(prev_debug_location); |
| | 10575 | } |
| | 10576 | } |
| | 10577 | |
| | 10578 | const entry_block = llvm_func.getFirstBasicBlock().?; |
| | 10579 | if (entry_block.getFirstInstruction()) |first_inst| { |
| | 10580 | builder.positionBuilder(entry_block, first_inst); |
| | 10581 | } else { |
| | 10582 | builder.positionBuilderAtEnd(entry_block); |
| 10533 | } | 10583 | } |
| | 10584 | builder.clearCurrentDebugLocation(); |
| | 10585 | |
| | 10586 | break :blk builder.buildAllocaInAddressSpace(llvm_ty, address_space, ""); |
| | 10587 | }; |
| | 10588 | |
| | 10589 | if (maybe_alignment) |alignment| { |
| | 10590 | alloca.setAlignment(alignment); |
| 10534 | } | 10591 | } |
| 10535 | | 10592 | |
| 10536 | const entry_block = llvm_func.getFirstBasicBlock().?; | 10593 | // The pointer returned from this function should have the generic address space, |
| 10537 | if (entry_block.getFirstInstruction()) |first_inst| { | 10594 | // if this isn't the case then cast it to the generic address space. |
| 10538 | builder.positionBuilder(entry_block, first_inst); | 10595 | if (address_space != llvm.address_space.default) { |
| 10539 | } else { | 10596 | return builder.buildAddrSpaceCast(alloca, llvm_ty.pointerType(llvm.address_space.default), ""); |
| 10540 | builder.positionBuilderAtEnd(entry_block); | | |
| 10541 | } | 10597 | } |
| 10542 | builder.clearCurrentDebugLocation(); | | |
| 10543 | | 10598 | |
| 10544 | return builder.buildAlloca(llvm_ty, ""); | 10599 | return alloca; |
| 10545 | } | 10600 | } |
| 10546 | | 10601 | |
| 10547 | fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 { | 10602 | fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 { |