| ... | ... | @@ -569,7 +569,7 @@ pub const Object = struct { |
| 569 | 569 | /// Therefore, this table keeps track of the mapping. |
| 570 | 570 | decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Global.Index), |
| 571 | 571 | /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction. |
| 572 | | named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value), |
| 572 | named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Function.Index), |
| 573 | 573 | /// Maps Zig types to LLVM types. The table memory is backed by the GPA of |
| 574 | 574 | /// the compiler. |
| 575 | 575 | /// TODO when InternPool garbage collection is implemented, this map needs |
| ... | ... | @@ -1210,7 +1210,7 @@ pub const Object = struct { |
| 1210 | 1210 | if (isByRef(param_ty, mod)) { |
| 1211 | 1211 | const alignment = param_ty.abiAlignment(mod); |
| 1212 | 1212 | const param_llvm_ty = param.typeOf(); |
| 1213 | | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1213 | const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1214 | 1214 | const store_inst = builder.buildStore(param, arg_ptr); |
| 1215 | 1215 | store_inst.setAlignment(alignment); |
| 1216 | 1216 | args.appendAssumeCapacity(arg_ptr); |
| ... | ... | @@ -1267,12 +1267,12 @@ pub const Object = struct { |
| 1267 | 1267 | |
| 1268 | 1268 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); |
| 1269 | 1269 | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); |
| 1270 | | const int_llvm_ty = o.context.intType(abi_size * 8); |
| 1270 | const int_llvm_ty = (try o.builder.intType(@intCast(abi_size * 8))).toLlvm(&o.builder); |
| 1271 | 1271 | const alignment = @max( |
| 1272 | 1272 | param_ty.abiAlignment(mod), |
| 1273 | 1273 | o.target_data.abiAlignmentOfType(int_llvm_ty), |
| 1274 | 1274 | ); |
| 1275 | | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1275 | const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1276 | 1276 | const store_inst = builder.buildStore(param, arg_ptr); |
| 1277 | 1277 | store_inst.setAlignment(alignment); |
| 1278 | 1278 | |
| ... | ... | @@ -1317,13 +1317,13 @@ pub const Object = struct { |
| 1317 | 1317 | }, |
| 1318 | 1318 | .multiple_llvm_types => { |
| 1319 | 1319 | assert(!it.byval_attr); |
| 1320 | | const field_types = it.llvm_types_buffer[0..it.types_len]; |
| 1320 | const field_types = it.types_buffer[0..it.types_len]; |
| 1321 | 1321 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1322 | 1322 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); |
| 1323 | 1323 | const param_alignment = param_ty.abiAlignment(mod); |
| 1324 | | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| 1325 | | const llvm_ty = o.context.structType(field_types.ptr, @as(c_uint, @intCast(field_types.len)), .False); |
| 1326 | | for (field_types, 0..) |_, field_i_usize| { |
| 1324 | const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, param_alignment, target); |
| 1325 | const llvm_ty = (try o.builder.structType(.normal, field_types)).toLlvm(&o.builder); |
| 1326 | for (0..field_types.len) |field_i_usize| { |
| 1327 | 1327 | const field_i = @as(c_uint, @intCast(field_i_usize)); |
| 1328 | 1328 | const param = llvm_func.getParam(llvm_arg_i); |
| 1329 | 1329 | llvm_arg_i += 1; |
| ... | ... | @@ -1344,7 +1344,7 @@ pub const Object = struct { |
| 1344 | 1344 | assert(!it.byval_attr); |
| 1345 | 1345 | const param = llvm_func.getParam(llvm_arg_i); |
| 1346 | 1346 | llvm_arg_i += 1; |
| 1347 | | const casted = builder.buildBitCast(param, o.context.halfType(), ""); |
| 1347 | const casted = builder.buildBitCast(param, Builder.Type.half.toLlvm(&o.builder), ""); |
| 1348 | 1348 | try args.ensureUnusedCapacity(1); |
| 1349 | 1349 | args.appendAssumeCapacity(casted); |
| 1350 | 1350 | }, |
| ... | ... | @@ -1355,7 +1355,7 @@ pub const Object = struct { |
| 1355 | 1355 | llvm_arg_i += 1; |
| 1356 | 1356 | |
| 1357 | 1357 | const alignment = param_ty.abiAlignment(mod); |
| 1358 | | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1358 | const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1359 | 1359 | _ = builder.buildStore(param, arg_ptr); |
| 1360 | 1360 | |
| 1361 | 1361 | if (isByRef(param_ty, mod)) { |
| ... | ... | @@ -1373,7 +1373,7 @@ pub const Object = struct { |
| 1373 | 1373 | llvm_arg_i += 1; |
| 1374 | 1374 | |
| 1375 | 1375 | const alignment = param_ty.abiAlignment(mod); |
| 1376 | | const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1376 | const arg_ptr = try o.buildAllocaInner(builder, llvm_func, false, param_llvm_ty, alignment, target); |
| 1377 | 1377 | _ = builder.buildStore(param, arg_ptr); |
| 1378 | 1378 | |
| 1379 | 1379 | if (isByRef(param_ty, mod)) { |
| ... | ... | @@ -3563,7 +3563,7 @@ pub const Object = struct { |
| 3563 | 3563 | const bigint = int_val.toBigInt(&bigint_space, mod); |
| 3564 | 3564 | |
| 3565 | 3565 | const int_info = tv.ty.intInfo(mod); |
| 3566 | | const llvm_type = o.context.intType(int_info.bits); |
| 3566 | const llvm_type = (try o.builder.intType(@intCast(int_info.bits))).toLlvm(&o.builder); |
| 3567 | 3567 | |
| 3568 | 3568 | const unsigned_val = v: { |
| 3569 | 3569 | if (bigint.limbs.len == 1) { |
| ... | ... | @@ -3587,26 +3587,26 @@ pub const Object = struct { |
| 3587 | 3587 | switch (tv.ty.floatBits(target)) { |
| 3588 | 3588 | 16 => { |
| 3589 | 3589 | const repr = @as(u16, @bitCast(tv.val.toFloat(f16, mod))); |
| 3590 | | const llvm_i16 = o.context.intType(16); |
| 3590 | const llvm_i16 = Builder.Type.i16.toLlvm(&o.builder); |
| 3591 | 3591 | const int = llvm_i16.constInt(repr, .False); |
| 3592 | 3592 | return int.constBitCast(llvm_ty); |
| 3593 | 3593 | }, |
| 3594 | 3594 | 32 => { |
| 3595 | 3595 | const repr = @as(u32, @bitCast(tv.val.toFloat(f32, mod))); |
| 3596 | | const llvm_i32 = o.context.intType(32); |
| 3596 | const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder); |
| 3597 | 3597 | const int = llvm_i32.constInt(repr, .False); |
| 3598 | 3598 | return int.constBitCast(llvm_ty); |
| 3599 | 3599 | }, |
| 3600 | 3600 | 64 => { |
| 3601 | 3601 | const repr = @as(u64, @bitCast(tv.val.toFloat(f64, mod))); |
| 3602 | | const llvm_i64 = o.context.intType(64); |
| 3602 | const llvm_i64 = Builder.Type.i64.toLlvm(&o.builder); |
| 3603 | 3603 | const int = llvm_i64.constInt(repr, .False); |
| 3604 | 3604 | return int.constBitCast(llvm_ty); |
| 3605 | 3605 | }, |
| 3606 | 3606 | 80 => { |
| 3607 | 3607 | const float = tv.val.toFloat(f80, mod); |
| 3608 | 3608 | const repr = std.math.break_f80(float); |
| 3609 | | const llvm_i80 = o.context.intType(80); |
| 3609 | const llvm_i80 = Builder.Type.i80.toLlvm(&o.builder); |
| 3610 | 3610 | var x = llvm_i80.constInt(repr.exp, .False); |
| 3611 | 3611 | x = x.constShl(llvm_i80.constInt(64, .False)); |
| 3612 | 3612 | x = x.constOr(llvm_i80.constInt(repr.fraction, .False)); |
| ... | ... | @@ -3623,7 +3623,7 @@ pub const Object = struct { |
| 3623 | 3623 | if (native_endian == .Big) { |
| 3624 | 3624 | std.mem.swap(u64, &buf[0], &buf[1]); |
| 3625 | 3625 | } |
| 3626 | | const int = o.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf); |
| 3626 | const int = Builder.Type.i128.toLlvm(&o.builder).constIntOfArbitraryPrecision(buf.len, &buf); |
| 3627 | 3627 | return int.constBitCast(llvm_ty); |
| 3628 | 3628 | }, |
| 3629 | 3629 | else => unreachable, |
| ... | ... | @@ -3660,7 +3660,7 @@ pub const Object = struct { |
| 3660 | 3660 | comptime assert(optional_layout_version == 3); |
| 3661 | 3661 | const payload_ty = tv.ty.optionalChild(mod); |
| 3662 | 3662 | |
| 3663 | | const llvm_i8 = o.context.intType(8); |
| 3663 | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 3664 | 3664 | const non_null_bit = switch (opt.val) { |
| 3665 | 3665 | .none => llvm_i8.constNull(), |
| 3666 | 3666 | else => llvm_i8.constInt(1, .False), |
| ... | ... | @@ -3761,7 +3761,7 @@ pub const Object = struct { |
| 3761 | 3761 | const elem_ty = vector_type.child.toType(); |
| 3762 | 3762 | const llvm_elems = try gpa.alloc(*llvm.Value, vector_type.len); |
| 3763 | 3763 | defer gpa.free(llvm_elems); |
| 3764 | | const llvm_i8 = o.context.intType(8); |
| 3764 | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 3765 | 3765 | for (llvm_elems, 0..) |*llvm_elem, i| { |
| 3766 | 3766 | llvm_elem.* = switch (aggregate.storage) { |
| 3767 | 3767 | .bytes => |bytes| llvm_i8.constInt(bytes[i], .False), |
| ... | ... | @@ -3802,7 +3802,7 @@ pub const Object = struct { |
| 3802 | 3802 | |
| 3803 | 3803 | const padding_len = offset - prev_offset; |
| 3804 | 3804 | if (padding_len > 0) { |
| 3805 | | const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3805 | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3806 | 3806 | // TODO make this and all other padding elsewhere in debug |
| 3807 | 3807 | // builds be 0xaa not undef. |
| 3808 | 3808 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| ... | ... | @@ -3824,7 +3824,7 @@ pub const Object = struct { |
| 3824 | 3824 | offset = std.mem.alignForward(u64, offset, big_align); |
| 3825 | 3825 | const padding_len = offset - prev_offset; |
| 3826 | 3826 | if (padding_len > 0) { |
| 3827 | | const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3827 | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3828 | 3828 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3829 | 3829 | } |
| 3830 | 3830 | } |
| ... | ... | @@ -3850,7 +3850,7 @@ pub const Object = struct { |
| 3850 | 3850 | if (struct_obj.layout == .Packed) { |
| 3851 | 3851 | assert(struct_obj.haveLayout()); |
| 3852 | 3852 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 3853 | | const int_llvm_ty = o.context.intType(@as(c_uint, @intCast(big_bits))); |
| 3853 | const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder); |
| 3854 | 3854 | const fields = struct_obj.fields.values(); |
| 3855 | 3855 | comptime assert(Type.packed_struct_layout_version == 2); |
| 3856 | 3856 | var running_int: *llvm.Value = int_llvm_ty.constNull(); |
| ... | ... | @@ -3863,7 +3863,7 @@ pub const Object = struct { |
| 3863 | 3863 | .val = try tv.val.fieldValue(mod, i), |
| 3864 | 3864 | }); |
| 3865 | 3865 | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); |
| 3866 | | const small_int_ty = o.context.intType(ty_bit_size); |
| 3866 | const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder); |
| 3867 | 3867 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 3868 | 3868 | non_int_val.constPtrToInt(small_int_ty) |
| 3869 | 3869 | else |
| ... | ... | @@ -3899,7 +3899,7 @@ pub const Object = struct { |
| 3899 | 3899 | |
| 3900 | 3900 | const padding_len = offset - prev_offset; |
| 3901 | 3901 | if (padding_len > 0) { |
| 3902 | | const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3902 | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3903 | 3903 | // TODO make this and all other padding elsewhere in debug |
| 3904 | 3904 | // builds be 0xaa not undef. |
| 3905 | 3905 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| ... | ... | @@ -3921,7 +3921,7 @@ pub const Object = struct { |
| 3921 | 3921 | offset = std.mem.alignForward(u64, offset, big_align); |
| 3922 | 3922 | const padding_len = offset - prev_offset; |
| 3923 | 3923 | if (padding_len > 0) { |
| 3924 | | const llvm_array_ty = o.context.intType(8).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3924 | const llvm_array_ty = Builder.Type.i8.toLlvm(&o.builder).arrayType(@as(c_uint, @intCast(padding_len))); |
| 3925 | 3925 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3926 | 3926 | } |
| 3927 | 3927 | } |
| ... | ... | @@ -3969,7 +3969,7 @@ pub const Object = struct { |
| 3969 | 3969 | return llvm_union_ty.constNull(); |
| 3970 | 3970 | const non_int_val = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3971 | 3971 | const ty_bit_size = @as(u16, @intCast(field_ty.bitSize(mod))); |
| 3972 | | const small_int_ty = o.context.intType(ty_bit_size); |
| 3972 | const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder); |
| 3973 | 3973 | const small_int_val = if (field_ty.isPtrAtRuntime(mod)) |
| 3974 | 3974 | non_int_val.constPtrToInt(small_int_ty) |
| 3975 | 3975 | else |
| ... | ... | @@ -3985,7 +3985,7 @@ pub const Object = struct { |
| 3985 | 3985 | const payload = p: { |
| 3986 | 3986 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3987 | 3987 | const padding_len = @as(c_uint, @intCast(layout.payload_size)); |
| 3988 | | break :p o.context.intType(8).arrayType(padding_len).getUndef(); |
| 3988 | break :p Builder.Type.i8.toLlvm(&o.builder).arrayType(padding_len).getUndef(); |
| 3989 | 3989 | } |
| 3990 | 3990 | const field = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3991 | 3991 | need_unnamed = need_unnamed or o.isUnnamedType(field_ty, field); |
| ... | ... | @@ -3995,7 +3995,7 @@ pub const Object = struct { |
| 3995 | 3995 | } |
| 3996 | 3996 | const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size)); |
| 3997 | 3997 | const fields: [2]*llvm.Value = .{ |
| 3998 | | field, o.context.intType(8).arrayType(padding_len).getUndef(), |
| 3998 | field, Builder.Type.i8.toLlvm(&o.builder).arrayType(padding_len).getUndef(), |
| 3999 | 3999 | }; |
| 4000 | 4000 | break :p o.context.constStruct(&fields, fields.len, .True); |
| 4001 | 4001 | }; |
| ... | ... | @@ -4020,7 +4020,7 @@ pub const Object = struct { |
| 4020 | 4020 | fields = .{ payload, llvm_tag_value, undefined }; |
| 4021 | 4021 | } |
| 4022 | 4022 | if (layout.padding != 0) { |
| 4023 | | fields[2] = o.context.intType(8).arrayType(layout.padding).getUndef(); |
| 4023 | fields[2] = Builder.Type.i8.toLlvm(&o.builder).arrayType(layout.padding).getUndef(); |
| 4024 | 4024 | fields_len = 3; |
| 4025 | 4025 | } |
| 4026 | 4026 | if (need_unnamed) { |
| ... | ... | @@ -4033,25 +4033,25 @@ pub const Object = struct { |
| 4033 | 4033 | } |
| 4034 | 4034 | } |
| 4035 | 4035 | |
| 4036 | | fn lowerIntAsPtr(o: *Object, val: Value) Error!*llvm.Value { |
| 4036 | fn lowerIntAsPtr(o: *Object, val: Value) Allocator.Error!*llvm.Value { |
| 4037 | 4037 | const mod = o.module; |
| 4038 | 4038 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 4039 | 4039 | .undef => return o.context.pointerType(0).getUndef(), |
| 4040 | 4040 | .int => { |
| 4041 | 4041 | var bigint_space: Value.BigIntSpace = undefined; |
| 4042 | 4042 | const bigint = val.toBigInt(&bigint_space, mod); |
| 4043 | | const llvm_int = lowerBigInt(o, Type.usize, bigint); |
| 4043 | const llvm_int = try lowerBigInt(o, Type.usize, bigint); |
| 4044 | 4044 | return llvm_int.constIntToPtr(o.context.pointerType(0)); |
| 4045 | 4045 | }, |
| 4046 | 4046 | else => unreachable, |
| 4047 | 4047 | } |
| 4048 | 4048 | } |
| 4049 | 4049 | |
| 4050 | | fn lowerBigInt(o: *Object, ty: Type, bigint: std.math.big.int.Const) *llvm.Value { |
| 4050 | fn lowerBigInt(o: *Object, ty: Type, bigint: std.math.big.int.Const) Allocator.Error!*llvm.Value { |
| 4051 | 4051 | const mod = o.module; |
| 4052 | 4052 | const int_info = ty.intInfo(mod); |
| 4053 | 4053 | assert(int_info.bits != 0); |
| 4054 | | const llvm_type = o.context.intType(int_info.bits); |
| 4054 | const llvm_type = (try o.builder.intType(@intCast(int_info.bits))).toLlvm(&o.builder); |
| 4055 | 4055 | |
| 4056 | 4056 | const unsigned_val = v: { |
| 4057 | 4057 | if (bigint.limbs.len == 1) { |
| ... | ... | @@ -4090,7 +4090,6 @@ pub const Object = struct { |
| 4090 | 4090 | |
| 4091 | 4091 | fn lowerParentPtr(o: *Object, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { |
| 4092 | 4092 | const mod = o.module; |
| 4093 | | const target = mod.getTarget(); |
| 4094 | 4093 | return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { |
| 4095 | 4094 | .decl => |decl| o.lowerParentPtrDecl(ptr_val, decl), |
| 4096 | 4095 | .mut_decl => |mut_decl| o.lowerParentPtrDecl(ptr_val, mut_decl.decl), |
| ... | ... | @@ -4107,7 +4106,7 @@ pub const Object = struct { |
| 4107 | 4106 | } |
| 4108 | 4107 | |
| 4109 | 4108 | const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; |
| 4110 | | const llvm_u32 = o.context.intType(32); |
| 4109 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 4111 | 4110 | const indices: [2]*llvm.Value = .{ |
| 4112 | 4111 | llvm_u32.constInt(0, .False), |
| 4113 | 4112 | llvm_u32.constInt(payload_offset, .False), |
| ... | ... | @@ -4128,7 +4127,7 @@ pub const Object = struct { |
| 4128 | 4127 | return parent_llvm_ptr; |
| 4129 | 4128 | } |
| 4130 | 4129 | |
| 4131 | | const llvm_u32 = o.context.intType(32); |
| 4130 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 4132 | 4131 | const indices: [2]*llvm.Value = .{ |
| 4133 | 4132 | llvm_u32.constInt(0, .False), |
| 4134 | 4133 | llvm_u32.constInt(0, .False), |
| ... | ... | @@ -4153,7 +4152,7 @@ pub const Object = struct { |
| 4153 | 4152 | const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); |
| 4154 | 4153 | |
| 4155 | 4154 | const field_index = @as(u32, @intCast(field_ptr.index)); |
| 4156 | | const llvm_u32 = o.context.intType(32); |
| 4155 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 4157 | 4156 | switch (parent_ty.zigTypeTag(mod)) { |
| 4158 | 4157 | .Union => { |
| 4159 | 4158 | if (parent_ty.containerLayout(mod) == .Packed) { |
| ... | ... | @@ -4180,7 +4179,7 @@ pub const Object = struct { |
| 4180 | 4179 | .Struct => { |
| 4181 | 4180 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 4182 | 4181 | if (!byte_aligned) return parent_llvm_ptr; |
| 4183 | | const llvm_usize = o.context.intType(target.ptrBitWidth()); |
| 4182 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 4184 | 4183 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 4185 | 4184 | // count bits of fields before this one |
| 4186 | 4185 | const prev_bits = b: { |
| ... | ... | @@ -4438,6 +4437,51 @@ pub const Object = struct { |
| 4438 | 4437 | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder)); |
| 4439 | 4438 | } |
| 4440 | 4439 | } |
| 4440 | |
| 4441 | fn buildAllocaInner( |
| 4442 | o: *Object, |
| 4443 | builder: *llvm.Builder, |
| 4444 | llvm_func: *llvm.Value, |
| 4445 | di_scope_non_null: bool, |
| 4446 | llvm_ty: *llvm.Type, |
| 4447 | maybe_alignment: ?c_uint, |
| 4448 | target: std.Target, |
| 4449 | ) Allocator.Error!*llvm.Value { |
| 4450 | const address_space = llvmAllocaAddressSpace(target); |
| 4451 | |
| 4452 | const alloca = blk: { |
| 4453 | const prev_block = builder.getInsertBlock(); |
| 4454 | const prev_debug_location = builder.getCurrentDebugLocation2(); |
| 4455 | defer { |
| 4456 | builder.positionBuilderAtEnd(prev_block); |
| 4457 | if (di_scope_non_null) { |
| 4458 | builder.setCurrentDebugLocation2(prev_debug_location); |
| 4459 | } |
| 4460 | } |
| 4461 | |
| 4462 | const entry_block = llvm_func.getFirstBasicBlock().?; |
| 4463 | if (entry_block.getFirstInstruction()) |first_inst| { |
| 4464 | builder.positionBuilder(entry_block, first_inst); |
| 4465 | } else { |
| 4466 | builder.positionBuilderAtEnd(entry_block); |
| 4467 | } |
| 4468 | builder.clearCurrentDebugLocation(); |
| 4469 | |
| 4470 | break :blk builder.buildAllocaInAddressSpace(llvm_ty, @intFromEnum(address_space), ""); |
| 4471 | }; |
| 4472 | |
| 4473 | if (maybe_alignment) |alignment| { |
| 4474 | alloca.setAlignment(alignment); |
| 4475 | } |
| 4476 | |
| 4477 | // The pointer returned from this function should have the generic address space, |
| 4478 | // if this isn't the case then cast it to the generic address space. |
| 4479 | if (address_space != .default) { |
| 4480 | return builder.buildAddrSpaceCast(alloca, Builder.Type.ptr.toLlvm(&o.builder), ""); |
| 4481 | } |
| 4482 | |
| 4483 | return alloca; |
| 4484 | } |
| 4441 | 4485 | }; |
| 4442 | 4486 | |
| 4443 | 4487 | pub const DeclGen = struct { |
| ... | ... | @@ -4934,7 +4978,7 @@ pub const FuncGen = struct { |
| 4934 | 4978 | |
| 4935 | 4979 | const ret_ptr = if (!sret) null else blk: { |
| 4936 | 4980 | const llvm_ret_ty = (try o.lowerType(return_type)).toLlvm(&o.builder); |
| 4937 | | const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(mod)); |
| 4981 | const ret_ptr = try self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(mod)); |
| 4938 | 4982 | try llvm_args.append(ret_ptr); |
| 4939 | 4983 | break :blk ret_ptr; |
| 4940 | 4984 | }; |
| ... | ... | @@ -4971,7 +5015,7 @@ pub const FuncGen = struct { |
| 4971 | 5015 | } else { |
| 4972 | 5016 | const alignment = param_ty.abiAlignment(mod); |
| 4973 | 5017 | const param_llvm_ty = llvm_arg.typeOf(); |
| 4974 | | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); |
| 5018 | const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment); |
| 4975 | 5019 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); |
| 4976 | 5020 | store_inst.setAlignment(alignment); |
| 4977 | 5021 | try llvm_args.append(arg_ptr); |
| ... | ... | @@ -4984,7 +5028,7 @@ pub const FuncGen = struct { |
| 4984 | 5028 | |
| 4985 | 5029 | const alignment = param_ty.abiAlignment(mod); |
| 4986 | 5030 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); |
| 4987 | | const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); |
| 5031 | const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment); |
| 4988 | 5032 | if (isByRef(param_ty, mod)) { |
| 4989 | 5033 | const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, ""); |
| 4990 | 5034 | load_inst.setAlignment(alignment); |
| ... | ... | @@ -5003,7 +5047,7 @@ pub const FuncGen = struct { |
| 5003 | 5047 | const param_ty = self.typeOf(arg); |
| 5004 | 5048 | const llvm_arg = try self.resolveInst(arg); |
| 5005 | 5049 | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); |
| 5006 | | const int_llvm_ty = self.context.intType(abi_size * 8); |
| 5050 | const int_llvm_ty = (try o.builder.intType(@intCast(abi_size * 8))).toLlvm(&o.builder); |
| 5007 | 5051 | |
| 5008 | 5052 | if (isByRef(param_ty, mod)) { |
| 5009 | 5053 | const alignment = param_ty.abiAlignment(mod); |
| ... | ... | @@ -5017,7 +5061,7 @@ pub const FuncGen = struct { |
| 5017 | 5061 | param_ty.abiAlignment(mod), |
| 5018 | 5062 | o.target_data.abiAlignmentOfType(int_llvm_ty), |
| 5019 | 5063 | ); |
| 5020 | | const int_ptr = self.buildAlloca(int_llvm_ty, alignment); |
| 5064 | const int_ptr = try self.buildAlloca(int_llvm_ty, alignment); |
| 5021 | 5065 | const store_inst = self.builder.buildStore(llvm_arg, int_ptr); |
| 5022 | 5066 | store_inst.setAlignment(alignment); |
| 5023 | 5067 | const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); |
| ... | ... | @@ -5037,22 +5081,22 @@ pub const FuncGen = struct { |
| 5037 | 5081 | .multiple_llvm_types => { |
| 5038 | 5082 | const arg = args[it.zig_index - 1]; |
| 5039 | 5083 | const param_ty = self.typeOf(arg); |
| 5040 | | const llvm_types = it.llvm_types_buffer[0..it.types_len]; |
| 5084 | const llvm_types = it.types_buffer[0..it.types_len]; |
| 5041 | 5085 | const llvm_arg = try self.resolveInst(arg); |
| 5042 | 5086 | const is_by_ref = isByRef(param_ty, mod); |
| 5043 | 5087 | const arg_ptr = if (is_by_ref) llvm_arg else p: { |
| 5044 | | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 5088 | const p = try self.buildAlloca(llvm_arg.typeOf(), null); |
| 5045 | 5089 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 5046 | 5090 | store_inst.setAlignment(param_ty.abiAlignment(mod)); |
| 5047 | 5091 | break :p p; |
| 5048 | 5092 | }; |
| 5049 | 5093 | |
| 5050 | | const llvm_ty = self.context.structType(llvm_types.ptr, @as(c_uint, @intCast(llvm_types.len)), .False); |
| 5094 | const llvm_ty = (try o.builder.structType(.normal, llvm_types)).toLlvm(&o.builder); |
| 5051 | 5095 | try llvm_args.ensureUnusedCapacity(it.types_len); |
| 5052 | 5096 | for (llvm_types, 0..) |field_ty, i_usize| { |
| 5053 | 5097 | const i = @as(c_uint, @intCast(i_usize)); |
| 5054 | 5098 | const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, i, ""); |
| 5055 | | const load_inst = self.builder.buildLoad(field_ty, field_ptr, ""); |
| 5099 | const load_inst = self.builder.buildLoad(field_ty.toLlvm(&o.builder), field_ptr, ""); |
| 5056 | 5100 | load_inst.setAlignment(target.ptrBitWidth() / 8); |
| 5057 | 5101 | llvm_args.appendAssumeCapacity(load_inst); |
| 5058 | 5102 | } |
| ... | ... | @@ -5060,7 +5104,7 @@ pub const FuncGen = struct { |
| 5060 | 5104 | .as_u16 => { |
| 5061 | 5105 | const arg = args[it.zig_index - 1]; |
| 5062 | 5106 | const llvm_arg = try self.resolveInst(arg); |
| 5063 | | const casted = self.builder.buildBitCast(llvm_arg, self.context.intType(16), ""); |
| 5107 | const casted = self.builder.buildBitCast(llvm_arg, Builder.Type.i16.toLlvm(&o.builder), ""); |
| 5064 | 5108 | try llvm_args.append(casted); |
| 5065 | 5109 | }, |
| 5066 | 5110 | .float_array => |count| { |
| ... | ... | @@ -5068,7 +5112,7 @@ pub const FuncGen = struct { |
| 5068 | 5112 | const arg_ty = self.typeOf(arg); |
| 5069 | 5113 | var llvm_arg = try self.resolveInst(arg); |
| 5070 | 5114 | if (!isByRef(arg_ty, mod)) { |
| 5071 | | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 5115 | const p = try self.buildAlloca(llvm_arg.typeOf(), null); |
| 5072 | 5116 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 5073 | 5117 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); |
| 5074 | 5118 | llvm_arg = store_inst; |
| ... | ... | @@ -5088,13 +5132,13 @@ pub const FuncGen = struct { |
| 5088 | 5132 | const arg_ty = self.typeOf(arg); |
| 5089 | 5133 | var llvm_arg = try self.resolveInst(arg); |
| 5090 | 5134 | if (!isByRef(arg_ty, mod)) { |
| 5091 | | const p = self.buildAlloca(llvm_arg.typeOf(), null); |
| 5135 | const p = try self.buildAlloca(llvm_arg.typeOf(), null); |
| 5092 | 5136 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 5093 | 5137 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); |
| 5094 | 5138 | llvm_arg = store_inst; |
| 5095 | 5139 | } |
| 5096 | 5140 | |
| 5097 | | const array_llvm_ty = self.context.intType(elem_size).arrayType(arr_len); |
| 5141 | const array_llvm_ty = (try o.builder.intType(@intCast(elem_size))).toLlvm(&o.builder).arrayType(arr_len); |
| 5098 | 5142 | const alignment = arg_ty.abiAlignment(mod); |
| 5099 | 5143 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); |
| 5100 | 5144 | load_inst.setAlignment(alignment); |
| ... | ... | @@ -5198,7 +5242,7 @@ pub const FuncGen = struct { |
| 5198 | 5242 | // a different LLVM type than the usual one. We solve this here at the callsite |
| 5199 | 5243 | // by using our canonical type, then loading it if necessary. |
| 5200 | 5244 | const alignment = o.target_data.abiAlignmentOfType(abi_ret_ty); |
| 5201 | | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 5245 | const rp = try self.buildAlloca(llvm_ret_ty, alignment); |
| 5202 | 5246 | const store_inst = self.builder.buildStore(call, rp); |
| 5203 | 5247 | store_inst.setAlignment(alignment); |
| 5204 | 5248 | if (isByRef(return_type, mod)) { |
| ... | ... | @@ -5214,7 +5258,7 @@ pub const FuncGen = struct { |
| 5214 | 5258 | // our by-ref status disagrees with sret so we must allocate, store, |
| 5215 | 5259 | // and return the allocation pointer. |
| 5216 | 5260 | const alignment = return_type.abiAlignment(mod); |
| 5217 | | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 5261 | const rp = try self.buildAlloca(llvm_ret_ty, alignment); |
| 5218 | 5262 | const store_inst = self.builder.buildStore(call, rp); |
| 5219 | 5263 | store_inst.setAlignment(alignment); |
| 5220 | 5264 | return rp; |
| ... | ... | @@ -5235,7 +5279,7 @@ pub const FuncGen = struct { |
| 5235 | 5279 | }); |
| 5236 | 5280 | const null_opt_addr_global = try o.getNullOptAddr(); |
| 5237 | 5281 | const target = mod.getTarget(); |
| 5238 | | const llvm_usize = fg.context.intType(target.ptrBitWidth()); |
| 5282 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5239 | 5283 | // example: |
| 5240 | 5284 | // call fastcc void @test2.panic( |
| 5241 | 5285 | // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr |
| ... | ... | @@ -5310,7 +5354,7 @@ pub const FuncGen = struct { |
| 5310 | 5354 | return null; |
| 5311 | 5355 | } |
| 5312 | 5356 | |
| 5313 | | const rp = self.buildAlloca(llvm_ret_ty, alignment); |
| 5357 | const rp = try self.buildAlloca(llvm_ret_ty, alignment); |
| 5314 | 5358 | const store_inst = self.builder.buildStore(operand, rp); |
| 5315 | 5359 | store_inst.setAlignment(alignment); |
| 5316 | 5360 | const load_inst = self.builder.buildLoad(abi_ret_ty, rp, ""); |
| ... | ... | @@ -5369,16 +5413,12 @@ pub const FuncGen = struct { |
| 5369 | 5413 | const mod = o.module; |
| 5370 | 5414 | |
| 5371 | 5415 | const result_alignment = va_list_ty.abiAlignment(mod); |
| 5372 | | const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5416 | const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5373 | 5417 | |
| 5374 | 5418 | const llvm_fn_name = "llvm.va_copy"; |
| 5375 | 5419 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 5376 | | const param_types = [_]*llvm.Type{ |
| 5377 | | self.context.pointerType(0), |
| 5378 | | self.context.pointerType(0), |
| 5379 | | }; |
| 5380 | | const fn_type = llvm.functionType(self.context.voidType(), &param_types, param_types.len, .False); |
| 5381 | | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); |
| 5420 | const fn_type = try o.builder.fnType(.void, &.{ .ptr, .ptr }, .normal); |
| 5421 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 5382 | 5422 | }; |
| 5383 | 5423 | |
| 5384 | 5424 | const args: [2]*llvm.Value = .{ dest_list, src_list }; |
| ... | ... | @@ -5400,9 +5440,8 @@ pub const FuncGen = struct { |
| 5400 | 5440 | |
| 5401 | 5441 | const llvm_fn_name = "llvm.va_end"; |
| 5402 | 5442 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 5403 | | const param_types = [_]*llvm.Type{self.context.pointerType(0)}; |
| 5404 | | const fn_type = llvm.functionType(self.context.voidType(), &param_types, param_types.len, .False); |
| 5405 | | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); |
| 5443 | const fn_type = try o.builder.fnType(.void, &.{.ptr}, .normal); |
| 5444 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 5406 | 5445 | }; |
| 5407 | 5446 | const args: [1]*llvm.Value = .{list}; |
| 5408 | 5447 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| ... | ... | @@ -5416,13 +5455,12 @@ pub const FuncGen = struct { |
| 5416 | 5455 | const llvm_va_list_ty = (try o.lowerType(va_list_ty)).toLlvm(&o.builder); |
| 5417 | 5456 | |
| 5418 | 5457 | const result_alignment = va_list_ty.abiAlignment(mod); |
| 5419 | | const list = self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5458 | const list = try self.buildAlloca(llvm_va_list_ty, result_alignment); |
| 5420 | 5459 | |
| 5421 | 5460 | const llvm_fn_name = "llvm.va_start"; |
| 5422 | 5461 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 5423 | | const param_types = [_]*llvm.Type{self.context.pointerType(0)}; |
| 5424 | | const fn_type = llvm.functionType(self.context.voidType(), &param_types, param_types.len, .False); |
| 5425 | | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); |
| 5462 | const fn_type = try o.builder.fnType(.void, &.{.ptr}, .normal); |
| 5463 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 5426 | 5464 | }; |
| 5427 | 5465 | const args: [1]*llvm.Value = .{list}; |
| 5428 | 5466 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| ... | ... | @@ -5495,7 +5533,7 @@ pub const FuncGen = struct { |
| 5495 | 5533 | const opt_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 5496 | 5534 | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); |
| 5497 | 5535 | const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); |
| 5498 | | const llvm_i2 = self.context.intType(2); |
| 5536 | const llvm_i2 = (try o.builder.intType(2)).toLlvm(&o.builder); |
| 5499 | 5537 | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); |
| 5500 | 5538 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); |
| 5501 | 5539 | const lhs_shifted = self.builder.buildShl(lhs_non_null_i2, llvm_i2.constInt(1, .False), ""); |
| ... | ... | @@ -5529,7 +5567,7 @@ pub const FuncGen = struct { |
| 5529 | 5567 | mixed_block, |
| 5530 | 5568 | both_pl_block_end, |
| 5531 | 5569 | }; |
| 5532 | | const llvm_i1 = self.context.intType(1); |
| 5570 | const llvm_i1 = Builder.Type.i1.toLlvm(&o.builder); |
| 5533 | 5571 | const llvm_i1_0 = llvm_i1.constInt(0, .False); |
| 5534 | 5572 | const llvm_i1_1 = llvm_i1.constInt(1, .False); |
| 5535 | 5573 | const incoming_values: [3]*llvm.Value = .{ |
| ... | ... | @@ -5767,13 +5805,11 @@ pub const FuncGen = struct { |
| 5767 | 5805 | |
| 5768 | 5806 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5769 | 5807 | const o = self.dg.object; |
| 5770 | | const mod = o.module; |
| 5771 | 5808 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5772 | 5809 | const cond = try self.resolveInst(pl_op.operand); |
| 5773 | 5810 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 5774 | 5811 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| 5775 | | const target = mod.getTarget(); |
| 5776 | | const llvm_usize = self.context.intType(target.ptrBitWidth()); |
| 5812 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5777 | 5813 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) |
| 5778 | 5814 | self.builder.buildPtrToInt(cond, llvm_usize, "") |
| 5779 | 5815 | else |
| ... | ... | @@ -5874,48 +5910,46 @@ pub const FuncGen = struct { |
| 5874 | 5910 | |
| 5875 | 5911 | const dest_ty = self.typeOfIndex(inst); |
| 5876 | 5912 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 5877 | | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 5913 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 5878 | 5914 | const target = mod.getTarget(); |
| 5879 | 5915 | |
| 5880 | 5916 | if (intrinsicsAllowed(dest_scalar_ty, target)) { |
| 5881 | 5917 | if (operand_scalar_ty.isSignedInt(mod)) { |
| 5882 | | return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); |
| 5918 | return self.builder.buildSIToFP(operand, dest_llvm_ty.toLlvm(&o.builder), ""); |
| 5883 | 5919 | } else { |
| 5884 | | return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); |
| 5920 | return self.builder.buildUIToFP(operand, dest_llvm_ty.toLlvm(&o.builder), ""); |
| 5885 | 5921 | } |
| 5886 | 5922 | } |
| 5887 | 5923 | |
| 5888 | 5924 | const operand_bits = @as(u16, @intCast(operand_scalar_ty.bitSize(mod))); |
| 5889 | 5925 | const rt_int_bits = compilerRtIntBits(operand_bits); |
| 5890 | | const rt_int_ty = self.context.intType(rt_int_bits); |
| 5926 | const rt_int_ty = try o.builder.intType(rt_int_bits); |
| 5891 | 5927 | var extended = e: { |
| 5892 | 5928 | if (operand_scalar_ty.isSignedInt(mod)) { |
| 5893 | | break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, ""); |
| 5929 | break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty.toLlvm(&o.builder), ""); |
| 5894 | 5930 | } else { |
| 5895 | | break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, ""); |
| 5931 | break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty.toLlvm(&o.builder), ""); |
| 5896 | 5932 | } |
| 5897 | 5933 | }; |
| 5898 | 5934 | const dest_bits = dest_scalar_ty.floatBits(target); |
| 5899 | 5935 | const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5900 | 5936 | const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); |
| 5901 | 5937 | const sign_prefix = if (operand_scalar_ty.isSignedInt(mod)) "" else "un"; |
| 5902 | | var fn_name_buf: [64]u8 = undefined; |
| 5903 | | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{ |
| 5938 | const fn_name = try o.builder.fmt("__float{s}{s}i{s}f", .{ |
| 5904 | 5939 | sign_prefix, |
| 5905 | 5940 | compiler_rt_operand_abbrev, |
| 5906 | 5941 | compiler_rt_dest_abbrev, |
| 5907 | | }) catch unreachable; |
| 5942 | }); |
| 5908 | 5943 | |
| 5909 | | var param_types = [1]*llvm.Type{rt_int_ty}; |
| 5944 | var param_type = rt_int_ty; |
| 5910 | 5945 | if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) { |
| 5911 | 5946 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard |
| 5912 | 5947 | // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. |
| 5913 | | const v2i64 = self.context.intType(64).vectorType(2); |
| 5914 | | extended = self.builder.buildBitCast(extended, v2i64, ""); |
| 5915 | | param_types = [1]*llvm.Type{v2i64}; |
| 5948 | param_type = try o.builder.vectorType(.normal, 2, .i64); |
| 5949 | extended = self.builder.buildBitCast(extended, param_type.toLlvm(&o.builder), ""); |
| 5916 | 5950 | } |
| 5917 | 5951 | |
| 5918 | | const libc_fn = try self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); |
| 5952 | const libc_fn = try self.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); |
| 5919 | 5953 | const params = [1]*llvm.Value{extended}; |
| 5920 | 5954 | |
| 5921 | 5955 | return self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, &params, params.len, .C, .Auto, ""); |
| ... | ... | @@ -5935,23 +5969,23 @@ pub const FuncGen = struct { |
| 5935 | 5969 | |
| 5936 | 5970 | const dest_ty = self.typeOfIndex(inst); |
| 5937 | 5971 | const dest_scalar_ty = dest_ty.scalarType(mod); |
| 5938 | | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 5972 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 5939 | 5973 | |
| 5940 | 5974 | if (intrinsicsAllowed(operand_scalar_ty, target)) { |
| 5941 | 5975 | // TODO set fast math flag |
| 5942 | 5976 | if (dest_scalar_ty.isSignedInt(mod)) { |
| 5943 | | return self.builder.buildFPToSI(operand, dest_llvm_ty, ""); |
| 5977 | return self.builder.buildFPToSI(operand, dest_llvm_ty.toLlvm(&o.builder), ""); |
| 5944 | 5978 | } else { |
| 5945 | | return self.builder.buildFPToUI(operand, dest_llvm_ty, ""); |
| 5979 | return self.builder.buildFPToUI(operand, dest_llvm_ty.toLlvm(&o.builder), ""); |
| 5946 | 5980 | } |
| 5947 | 5981 | } |
| 5948 | 5982 | |
| 5949 | | const rt_int_bits = compilerRtIntBits(@as(u16, @intCast(dest_scalar_ty.bitSize(mod)))); |
| 5950 | | const ret_ty = self.context.intType(rt_int_bits); |
| 5983 | const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(mod))); |
| 5984 | const ret_ty = try o.builder.intType(rt_int_bits); |
| 5951 | 5985 | const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { |
| 5952 | 5986 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard |
| 5953 | 5987 | // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. |
| 5954 | | break :b self.context.intType(64).vectorType(2); |
| 5988 | break :b try o.builder.vectorType(.normal, 2, .i64); |
| 5955 | 5989 | } else ret_ty; |
| 5956 | 5990 | |
| 5957 | 5991 | const operand_bits = operand_scalar_ty.floatBits(target); |
| ... | ... | @@ -5960,22 +5994,20 @@ pub const FuncGen = struct { |
| 5960 | 5994 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5961 | 5995 | const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns"; |
| 5962 | 5996 | |
| 5963 | | var fn_name_buf: [64]u8 = undefined; |
| 5964 | | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{ |
| 5997 | const fn_name = try o.builder.fmt("__fix{s}{s}f{s}i", .{ |
| 5965 | 5998 | sign_prefix, |
| 5966 | 5999 | compiler_rt_operand_abbrev, |
| 5967 | 6000 | compiler_rt_dest_abbrev, |
| 5968 | | }) catch unreachable; |
| 6001 | }); |
| 5969 | 6002 | |
| 5970 | | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 5971 | | const param_types = [1]*llvm.Type{operand_llvm_ty}; |
| 5972 | | const libc_fn = try self.getLibcFunction(fn_name, &param_types, libc_ret_ty); |
| 6003 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 6004 | const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); |
| 5973 | 6005 | const params = [1]*llvm.Value{operand}; |
| 5974 | 6006 | |
| 5975 | 6007 | var result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, &params, params.len, .C, .Auto, ""); |
| 5976 | 6008 | |
| 5977 | | if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); |
| 5978 | | if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); |
| 6009 | if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty.toLlvm(&o.builder), ""); |
| 6010 | if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty.toLlvm(&o.builder), ""); |
| 5979 | 6011 | return result; |
| 5980 | 6012 | } |
| 5981 | 6013 | |
| ... | ... | @@ -5989,11 +6021,10 @@ pub const FuncGen = struct { |
| 5989 | 6021 | } |
| 5990 | 6022 | } |
| 5991 | 6023 | |
| 5992 | | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { |
| 6024 | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) Allocator.Error!*llvm.Value { |
| 5993 | 6025 | const o = fg.dg.object; |
| 5994 | 6026 | const mod = o.module; |
| 5995 | | const target = mod.getTarget(); |
| 5996 | | const llvm_usize_ty = fg.context.intType(target.ptrBitWidth()); |
| 6027 | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5997 | 6028 | switch (ty.ptrSize(mod)) { |
| 5998 | 6029 | .Slice => { |
| 5999 | 6030 | const len = fg.builder.buildExtractValue(ptr, 1, ""); |
| ... | ... | @@ -6080,7 +6111,7 @@ pub const FuncGen = struct { |
| 6080 | 6111 | const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder); |
| 6081 | 6112 | const elem_ty = array_ty.childType(mod); |
| 6082 | 6113 | if (isByRef(array_ty, mod)) { |
| 6083 | | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| 6114 | const indices: [2]*llvm.Value = .{ Builder.Type.i32.toLlvm(&o.builder).constNull(), rhs }; |
| 6084 | 6115 | if (isByRef(elem_ty, mod)) { |
| 6085 | 6116 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); |
| 6086 | 6117 | if (canElideLoad(self, body_tail)) |
| ... | ... | @@ -6128,7 +6159,7 @@ pub const FuncGen = struct { |
| 6128 | 6159 | // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch |
| 6129 | 6160 | const ptr = if (ptr_ty.isSinglePointer(mod)) ptr: { |
| 6130 | 6161 | // If this is a single-item pointer to an array, we need another index in the GEP. |
| 6131 | | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| 6162 | const indices: [2]*llvm.Value = .{ Builder.Type.i32.toLlvm(&o.builder).constNull(), rhs }; |
| 6132 | 6163 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6133 | 6164 | } else ptr: { |
| 6134 | 6165 | const indices: [1]*llvm.Value = .{rhs}; |
| ... | ... | @@ -6162,7 +6193,7 @@ pub const FuncGen = struct { |
| 6162 | 6193 | const llvm_elem_ty = (try o.lowerPtrElemTy(elem_ty)).toLlvm(&o.builder); |
| 6163 | 6194 | if (ptr_ty.isSinglePointer(mod)) { |
| 6164 | 6195 | // If this is a single-item pointer to an array, we need another index in the GEP. |
| 6165 | | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; |
| 6196 | const indices: [2]*llvm.Value = .{ Builder.Type.i32.toLlvm(&o.builder).constNull(), rhs }; |
| 6166 | 6197 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6167 | 6198 | } else { |
| 6168 | 6199 | const indices: [1]*llvm.Value = .{rhs}; |
| ... | ... | @@ -6216,12 +6247,12 @@ pub const FuncGen = struct { |
| 6216 | 6247 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); |
| 6217 | 6248 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6218 | 6249 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6219 | | const same_size_int = self.context.intType(elem_bits); |
| 6250 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6220 | 6251 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6221 | 6252 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6222 | 6253 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6223 | 6254 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6224 | | const same_size_int = self.context.intType(elem_bits); |
| 6255 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6225 | 6256 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6226 | 6257 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 6227 | 6258 | } |
| ... | ... | @@ -6238,12 +6269,12 @@ pub const FuncGen = struct { |
| 6238 | 6269 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); |
| 6239 | 6270 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6240 | 6271 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6241 | | const same_size_int = self.context.intType(elem_bits); |
| 6272 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6242 | 6273 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6243 | 6274 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6244 | 6275 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6245 | 6276 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); |
| 6246 | | const same_size_int = self.context.intType(elem_bits); |
| 6277 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 6247 | 6278 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6248 | 6279 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 6249 | 6280 | } |
| ... | ... | @@ -6302,7 +6333,6 @@ pub const FuncGen = struct { |
| 6302 | 6333 | |
| 6303 | 6334 | const field_ptr = try self.resolveInst(extra.field_ptr); |
| 6304 | 6335 | |
| 6305 | | const target = o.module.getTarget(); |
| 6306 | 6336 | const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod); |
| 6307 | 6337 | const field_offset = parent_ty.structFieldOffset(extra.field_index, mod); |
| 6308 | 6338 | |
| ... | ... | @@ -6310,7 +6340,7 @@ pub const FuncGen = struct { |
| 6310 | 6340 | if (field_offset == 0) { |
| 6311 | 6341 | return field_ptr; |
| 6312 | 6342 | } |
| 6313 | | const llvm_usize_ty = self.context.intType(target.ptrBitWidth()); |
| 6343 | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 6314 | 6344 | |
| 6315 | 6345 | const field_ptr_int = self.builder.buildPtrToInt(field_ptr, llvm_usize_ty, ""); |
| 6316 | 6346 | const base_ptr_int = self.builder.buildNUWSub(field_ptr_int, llvm_usize_ty.constInt(field_offset, .False), ""); |
| ... | ... | @@ -6493,7 +6523,7 @@ pub const FuncGen = struct { |
| 6493 | 6523 | _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); |
| 6494 | 6524 | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 6495 | 6525 | const alignment = operand_ty.abiAlignment(mod); |
| 6496 | | const alloca = self.buildAlloca(operand.typeOf(), alignment); |
| 6526 | const alloca = try self.buildAlloca(operand.typeOf(), alignment); |
| 6497 | 6527 | const store_inst = self.builder.buildStore(operand, alloca); |
| 6498 | 6528 | store_inst.setAlignment(alignment); |
| 6499 | 6529 | _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); |
| ... | ... | @@ -6532,7 +6562,7 @@ pub const FuncGen = struct { |
| 6532 | 6562 | // The exact number of return / parameter values depends on which output values |
| 6533 | 6563 | // are passed by reference as indirect outputs (determined below). |
| 6534 | 6564 | const max_return_count = outputs.len; |
| 6535 | | const llvm_ret_types = try arena.alloc(*llvm.Type, max_return_count); |
| 6565 | const llvm_ret_types = try arena.alloc(Builder.Type, max_return_count); |
| 6536 | 6566 | const llvm_ret_indirect = try arena.alloc(bool, max_return_count); |
| 6537 | 6567 | |
| 6538 | 6568 | const max_param_count = inputs.len + outputs.len; |
| ... | ... | @@ -6571,7 +6601,7 @@ pub const FuncGen = struct { |
| 6571 | 6601 | const output_inst = try self.resolveInst(output); |
| 6572 | 6602 | const output_ty = self.typeOf(output); |
| 6573 | 6603 | assert(output_ty.zigTypeTag(mod) == .Pointer); |
| 6574 | | const elem_llvm_ty = (try o.lowerPtrElemTy(output_ty.childType(mod))).toLlvm(&o.builder); |
| 6604 | const elem_llvm_ty = try o.lowerPtrElemTy(output_ty.childType(mod)); |
| 6575 | 6605 | |
| 6576 | 6606 | if (llvm_ret_indirect[i]) { |
| 6577 | 6607 | // Pass the result by reference as an indirect output (e.g. "=*m") |
| ... | ... | @@ -6579,7 +6609,7 @@ pub const FuncGen = struct { |
| 6579 | 6609 | |
| 6580 | 6610 | llvm_param_values[llvm_param_i] = output_inst; |
| 6581 | 6611 | llvm_param_types[llvm_param_i] = output_inst.typeOf(); |
| 6582 | | llvm_param_attrs[llvm_param_i] = elem_llvm_ty; |
| 6612 | llvm_param_attrs[llvm_param_i] = elem_llvm_ty.toLlvm(&o.builder); |
| 6583 | 6613 | llvm_param_i += 1; |
| 6584 | 6614 | } else { |
| 6585 | 6615 | // Pass the result directly (e.g. "=r") |
| ... | ... | @@ -6588,7 +6618,7 @@ pub const FuncGen = struct { |
| 6588 | 6618 | } |
| 6589 | 6619 | } else { |
| 6590 | 6620 | const ret_ty = self.typeOfIndex(inst); |
| 6591 | | llvm_ret_types[llvm_ret_i] = (try o.lowerType(ret_ty)).toLlvm(&o.builder); |
| 6621 | llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty); |
| 6592 | 6622 | llvm_ret_i += 1; |
| 6593 | 6623 | } |
| 6594 | 6624 | |
| ... | ... | @@ -6623,9 +6653,9 @@ pub const FuncGen = struct { |
| 6623 | 6653 | |
| 6624 | 6654 | const arg_llvm_value = try self.resolveInst(input); |
| 6625 | 6655 | const arg_ty = self.typeOf(input); |
| 6626 | | var llvm_elem_ty: ?*llvm.Type = null; |
| 6656 | var llvm_elem_ty: Builder.Type = .none; |
| 6627 | 6657 | if (isByRef(arg_ty, mod)) { |
| 6628 | | llvm_elem_ty = (try o.lowerPtrElemTy(arg_ty)).toLlvm(&o.builder); |
| 6658 | llvm_elem_ty = try o.lowerPtrElemTy(arg_ty); |
| 6629 | 6659 | if (constraintAllowsMemory(constraint)) { |
| 6630 | 6660 | llvm_param_values[llvm_param_i] = arg_llvm_value; |
| 6631 | 6661 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| ... | ... | @@ -6643,7 +6673,7 @@ pub const FuncGen = struct { |
| 6643 | 6673 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| 6644 | 6674 | } else { |
| 6645 | 6675 | const alignment = arg_ty.abiAlignment(mod); |
| 6646 | | const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment); |
| 6676 | const arg_ptr = try self.buildAlloca(arg_llvm_value.typeOf(), alignment); |
| 6647 | 6677 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); |
| 6648 | 6678 | store_inst.setAlignment(alignment); |
| 6649 | 6679 | llvm_param_values[llvm_param_i] = arg_ptr; |
| ... | ... | @@ -6671,8 +6701,10 @@ pub const FuncGen = struct { |
| 6671 | 6701 | // In the case of indirect inputs, LLVM requires the callsite to have |
| 6672 | 6702 | // an elementtype(<ty>) attribute. |
| 6673 | 6703 | if (constraint[0] == '*') { |
| 6674 | | llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse |
| 6675 | | (try o.lowerPtrElemTy(arg_ty.childType(mod))).toLlvm(&o.builder); |
| 6704 | llvm_param_attrs[llvm_param_i] = (if (llvm_elem_ty != .none) |
| 6705 | llvm_elem_ty |
| 6706 | else |
| 6707 | try o.lowerPtrElemTy(arg_ty.childType(mod))).toLlvm(&o.builder); |
| 6676 | 6708 | } else { |
| 6677 | 6709 | llvm_param_attrs[llvm_param_i] = null; |
| 6678 | 6710 | } |
| ... | ... | @@ -6792,17 +6824,13 @@ pub const FuncGen = struct { |
| 6792 | 6824 | } |
| 6793 | 6825 | |
| 6794 | 6826 | const ret_llvm_ty = switch (return_count) { |
| 6795 | | 0 => self.context.voidType(), |
| 6827 | 0 => .void, |
| 6796 | 6828 | 1 => llvm_ret_types[0], |
| 6797 | | else => self.context.structType( |
| 6798 | | llvm_ret_types.ptr, |
| 6799 | | @as(c_uint, @intCast(return_count)), |
| 6800 | | .False, |
| 6801 | | ), |
| 6829 | else => try o.builder.structType(.normal, llvm_ret_types), |
| 6802 | 6830 | }; |
| 6803 | 6831 | |
| 6804 | 6832 | const llvm_fn_ty = llvm.functionType( |
| 6805 | | ret_llvm_ty, |
| 6833 | ret_llvm_ty.toLlvm(&o.builder), |
| 6806 | 6834 | llvm_param_types.ptr, |
| 6807 | 6835 | @as(c_uint, @intCast(param_count)), |
| 6808 | 6836 | .False, |
| ... | ... | @@ -6891,7 +6919,7 @@ pub const FuncGen = struct { |
| 6891 | 6919 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| 6892 | 6920 | else |
| 6893 | 6921 | operand; |
| 6894 | | const llvm_i8 = self.context.intType(8); |
| 6922 | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 6895 | 6923 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); |
| 6896 | 6924 | } |
| 6897 | 6925 | |
| ... | ... | @@ -6921,7 +6949,7 @@ pub const FuncGen = struct { |
| 6921 | 6949 | const zero = err_set_ty.constNull(); |
| 6922 | 6950 | |
| 6923 | 6951 | if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { |
| 6924 | | const llvm_i1 = self.context.intType(1); |
| 6952 | const llvm_i1 = Builder.Type.i1.toLlvm(&o.builder); |
| 6925 | 6953 | switch (op) { |
| 6926 | 6954 | .EQ => return llvm_i1.constInt(1, .False), // 0 == 0 |
| 6927 | 6955 | .NE => return llvm_i1.constInt(0, .False), // 0 != 0 |
| ... | ... | @@ -6979,7 +7007,7 @@ pub const FuncGen = struct { |
| 6979 | 7007 | const operand = try self.resolveInst(ty_op.operand); |
| 6980 | 7008 | const optional_ty = self.typeOf(ty_op.operand).childType(mod); |
| 6981 | 7009 | const payload_ty = optional_ty.optionalChild(mod); |
| 6982 | | const non_null_bit = self.context.intType(8).constInt(1, .False); |
| 7010 | const non_null_bit = Builder.Type.i8.toLlvm(&o.builder).constInt(1, .False); |
| 6983 | 7011 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6984 | 7012 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 6985 | 7013 | _ = self.builder.buildStore(non_null_bit, operand); |
| ... | ... | @@ -7165,7 +7193,7 @@ pub const FuncGen = struct { |
| 7165 | 7193 | const mod = o.module; |
| 7166 | 7194 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 7167 | 7195 | const payload_ty = self.typeOf(ty_op.operand); |
| 7168 | | const non_null_bit = self.context.intType(8).constInt(1, .False); |
| 7196 | const non_null_bit = Builder.Type.i8.toLlvm(&o.builder).constInt(1, .False); |
| 7169 | 7197 | comptime assert(optional_layout_version == 3); |
| 7170 | 7198 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit; |
| 7171 | 7199 | const operand = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -7175,7 +7203,7 @@ pub const FuncGen = struct { |
| 7175 | 7203 | } |
| 7176 | 7204 | const llvm_optional_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder); |
| 7177 | 7205 | if (isByRef(optional_ty, mod)) { |
| 7178 | | const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod)); |
| 7206 | const optional_ptr = try self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod)); |
| 7179 | 7207 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); |
| 7180 | 7208 | const payload_ptr_ty = try mod.singleMutPtrType(payload_ty); |
| 7181 | 7209 | try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); |
| ... | ... | @@ -7203,7 +7231,7 @@ pub const FuncGen = struct { |
| 7203 | 7231 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 7204 | 7232 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 7205 | 7233 | if (isByRef(err_un_ty, mod)) { |
| 7206 | | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod)); |
| 7234 | const result_ptr = try self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod)); |
| 7207 | 7235 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 7208 | 7236 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); |
| 7209 | 7237 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| ... | ... | @@ -7232,7 +7260,7 @@ pub const FuncGen = struct { |
| 7232 | 7260 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 7233 | 7261 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 7234 | 7262 | if (isByRef(err_un_ty, mod)) { |
| 7235 | | const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod)); |
| 7263 | const result_ptr = try self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod)); |
| 7236 | 7264 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 7237 | 7265 | const store_inst = self.builder.buildStore(operand, err_ptr); |
| 7238 | 7266 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| ... | ... | @@ -7252,8 +7280,8 @@ pub const FuncGen = struct { |
| 7252 | 7280 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7253 | 7281 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7254 | 7282 | const index = pl_op.payload; |
| 7255 | | const llvm_u32 = self.context.intType(32); |
| 7256 | | const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); |
| 7283 | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7284 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32}); |
| 7257 | 7285 | const args: [1]*llvm.Value = .{llvm_u32.constInt(index, .False)}; |
| 7258 | 7286 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 7259 | 7287 | } |
| ... | ... | @@ -7262,8 +7290,8 @@ pub const FuncGen = struct { |
| 7262 | 7290 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7263 | 7291 | const index = pl_op.payload; |
| 7264 | 7292 | const operand = try self.resolveInst(pl_op.operand); |
| 7265 | | const llvm_u32 = self.context.intType(32); |
| 7266 | | const llvm_fn = self.getIntrinsic("llvm.wasm.memory.grow", &.{llvm_u32}); |
| 7293 | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7294 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32}); |
| 7267 | 7295 | const args: [2]*llvm.Value = .{ |
| 7268 | 7296 | llvm_u32.constInt(index, .False), |
| 7269 | 7297 | operand, |
| ... | ... | @@ -7371,8 +7399,7 @@ pub const FuncGen = struct { |
| 7371 | 7399 | true => signed_intrinsic, |
| 7372 | 7400 | false => unsigned_intrinsic, |
| 7373 | 7401 | }; |
| 7374 | | const llvm_inst_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder); |
| 7375 | | const llvm_fn = fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty}); |
| 7402 | const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{try o.lowerType(inst_ty)}); |
| 7376 | 7403 | const result_struct = fg.builder.buildCall( |
| 7377 | 7404 | llvm_fn.globalGetValueType(), |
| 7378 | 7405 | llvm_fn, |
| ... | ... | @@ -7658,7 +7685,7 @@ pub const FuncGen = struct { |
| 7658 | 7685 | switch (ptr_ty.ptrSize(mod)) { |
| 7659 | 7686 | .One => { |
| 7660 | 7687 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 7661 | | const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), offset }; |
| 7688 | const indices: [2]*llvm.Value = .{ Builder.Type.i32.toLlvm(&o.builder).constNull(), offset }; |
| 7662 | 7689 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); |
| 7663 | 7690 | }, |
| 7664 | 7691 | .C, .Many => { |
| ... | ... | @@ -7687,7 +7714,7 @@ pub const FuncGen = struct { |
| 7687 | 7714 | .One => { |
| 7688 | 7715 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 7689 | 7716 | const indices: [2]*llvm.Value = .{ |
| 7690 | | self.context.intType(32).constNull(), negative_offset, |
| 7717 | Builder.Type.i32.toLlvm(&o.builder).constNull(), negative_offset, |
| 7691 | 7718 | }; |
| 7692 | 7719 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); |
| 7693 | 7720 | }, |
| ... | ... | @@ -7723,10 +7750,9 @@ pub const FuncGen = struct { |
| 7723 | 7750 | |
| 7724 | 7751 | const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; |
| 7725 | 7752 | |
| 7726 | | const llvm_lhs_ty = (try o.lowerType(lhs_ty)).toLlvm(&o.builder); |
| 7727 | 7753 | const llvm_dest_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 7728 | 7754 | |
| 7729 | | const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); |
| 7755 | const llvm_fn = try self.getIntrinsic(intrinsic_name, &.{try o.lowerType(lhs_ty)}); |
| 7730 | 7756 | const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); |
| 7731 | 7757 | |
| 7732 | 7758 | const result = self.builder.buildExtractValue(result_struct, 0, ""); |
| ... | ... | @@ -7737,7 +7763,7 @@ pub const FuncGen = struct { |
| 7737 | 7763 | |
| 7738 | 7764 | if (isByRef(dest_ty, mod)) { |
| 7739 | 7765 | const result_alignment = dest_ty.abiAlignment(mod); |
| 7740 | | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); |
| 7766 | const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment); |
| 7741 | 7767 | { |
| 7742 | 7768 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 7743 | 7769 | const store_inst = self.builder.buildStore(result, field_ptr); |
| ... | ... | @@ -7764,7 +7790,7 @@ pub const FuncGen = struct { |
| 7764 | 7790 | vector_len: usize, |
| 7765 | 7791 | ) !*llvm.Value { |
| 7766 | 7792 | const args_len = @as(c_uint, @intCast(args_vectors.len)); |
| 7767 | | const llvm_i32 = self.context.intType(32); |
| 7793 | const llvm_i32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7768 | 7794 | assert(args_len <= 3); |
| 7769 | 7795 | |
| 7770 | 7796 | var i: usize = 0; |
| ... | ... | @@ -7784,23 +7810,21 @@ pub const FuncGen = struct { |
| 7784 | 7810 | |
| 7785 | 7811 | fn getLibcFunction( |
| 7786 | 7812 | self: *FuncGen, |
| 7787 | | fn_name: [:0]const u8, |
| 7788 | | param_types: []const *llvm.Type, |
| 7789 | | return_type: *llvm.Type, |
| 7813 | fn_name: Builder.String, |
| 7814 | param_types: []const Builder.Type, |
| 7815 | return_type: Builder.Type, |
| 7790 | 7816 | ) Allocator.Error!*llvm.Value { |
| 7791 | 7817 | const o = self.dg.object; |
| 7792 | | return o.llvm_module.getNamedFunction(fn_name.ptr) orelse b: { |
| 7793 | | const alias = o.llvm_module.getNamedGlobalAlias(fn_name.ptr, fn_name.len); |
| 7818 | const slice = fn_name.toSlice(&o.builder).?; |
| 7819 | return o.llvm_module.getNamedFunction(slice) orelse b: { |
| 7820 | const alias = o.llvm_module.getNamedGlobalAlias(slice.ptr, slice.len); |
| 7794 | 7821 | break :b if (alias) |a| a.getAliasee() else null; |
| 7795 | 7822 | } orelse b: { |
| 7796 | | const name = try o.builder.string(fn_name); |
| 7797 | | |
| 7798 | | const params_len = @as(c_uint, @intCast(param_types.len)); |
| 7799 | | const fn_type = llvm.functionType(return_type, param_types.ptr, params_len, .False); |
| 7800 | | const f = o.llvm_module.addFunction(name.toSlice(&o.builder).?, fn_type); |
| 7823 | const fn_type = try o.builder.fnType(return_type, param_types, .normal); |
| 7824 | const f = o.llvm_module.addFunction(slice, fn_type.toLlvm(&o.builder)); |
| 7801 | 7825 | |
| 7802 | 7826 | var global = Builder.Global{ |
| 7803 | | .type = try o.builder.fnType(.void, &.{}, .normal), |
| 7827 | .type = fn_type, |
| 7804 | 7828 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, |
| 7805 | 7829 | }; |
| 7806 | 7830 | var function = Builder.Function{ |
| ... | ... | @@ -7808,9 +7832,8 @@ pub const FuncGen = struct { |
| 7808 | 7832 | }; |
| 7809 | 7833 | |
| 7810 | 7834 | try o.builder.llvm_globals.append(self.gpa, f); |
| 7811 | | _ = try o.builder.addGlobal(name, global); |
| 7835 | _ = try o.builder.addGlobal(fn_name, global); |
| 7812 | 7836 | try o.builder.functions.append(self.gpa, function); |
| 7813 | | |
| 7814 | 7837 | break :b f; |
| 7815 | 7838 | }; |
| 7816 | 7839 | } |
| ... | ... | @@ -7827,7 +7850,7 @@ pub const FuncGen = struct { |
| 7827 | 7850 | const mod = o.module; |
| 7828 | 7851 | const target = o.module.getTarget(); |
| 7829 | 7852 | const scalar_ty = ty.scalarType(mod); |
| 7830 | | const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 7853 | const scalar_llvm_ty = try o.lowerType(scalar_ty); |
| 7831 | 7854 | |
| 7832 | 7855 | if (intrinsicsAllowed(scalar_ty, target)) { |
| 7833 | 7856 | const llvm_predicate: llvm.RealPredicate = switch (pred) { |
| ... | ... | @@ -7843,7 +7866,6 @@ pub const FuncGen = struct { |
| 7843 | 7866 | |
| 7844 | 7867 | const float_bits = scalar_ty.floatBits(target); |
| 7845 | 7868 | const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits); |
| 7846 | | var fn_name_buf: [64]u8 = undefined; |
| 7847 | 7869 | const fn_base_name = switch (pred) { |
| 7848 | 7870 | .neq => "ne", |
| 7849 | 7871 | .eq => "eq", |
| ... | ... | @@ -7852,15 +7874,15 @@ pub const FuncGen = struct { |
| 7852 | 7874 | .gt => "gt", |
| 7853 | 7875 | .gte => "ge", |
| 7854 | 7876 | }; |
| 7855 | | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f2", .{ |
| 7856 | | fn_base_name, compiler_rt_float_abbrev, |
| 7857 | | }) catch unreachable; |
| 7877 | const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); |
| 7858 | 7878 | |
| 7859 | | const param_types = [2]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty }; |
| 7860 | | const llvm_i32 = self.context.intType(32); |
| 7861 | | const libc_fn = try self.getLibcFunction(fn_name, param_types[0..], llvm_i32); |
| 7879 | const libc_fn = try self.getLibcFunction( |
| 7880 | fn_name, |
| 7881 | ([1]Builder.Type{scalar_llvm_ty} ** 2)[0..], |
| 7882 | .i32, |
| 7883 | ); |
| 7862 | 7884 | |
| 7863 | | const zero = llvm_i32.constInt(0, .False); |
| 7885 | const zero = Builder.Type.i32.toLlvm(&o.builder).constInt(0, .False); |
| 7864 | 7886 | const int_pred: llvm.IntPredicate = switch (pred) { |
| 7865 | 7887 | .eq => .EQ, |
| 7866 | 7888 | .neq => .NE, |
| ... | ... | @@ -7872,7 +7894,7 @@ pub const FuncGen = struct { |
| 7872 | 7894 | |
| 7873 | 7895 | if (ty.zigTypeTag(mod) == .Vector) { |
| 7874 | 7896 | const vec_len = ty.vectorLen(mod); |
| 7875 | | const vector_result_ty = llvm_i32.vectorType(vec_len); |
| 7897 | const vector_result_ty = (try o.builder.vectorType(.normal, vec_len, .i32)).toLlvm(&o.builder); |
| 7876 | 7898 | |
| 7877 | 7899 | var result = vector_result_ty.getUndef(); |
| 7878 | 7900 | result = try self.buildElementwiseCall(libc_fn, &params, result, vec_len); |
| ... | ... | @@ -7913,7 +7935,7 @@ pub const FuncGen = struct { |
| 7913 | 7935 | |
| 7914 | 7936 | const FloatOpStrat = union(enum) { |
| 7915 | 7937 | intrinsic: []const u8, |
| 7916 | | libc: [:0]const u8, |
| 7938 | libc: Builder.String, |
| 7917 | 7939 | }; |
| 7918 | 7940 | |
| 7919 | 7941 | /// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.) |
| ... | ... | @@ -7930,11 +7952,10 @@ pub const FuncGen = struct { |
| 7930 | 7952 | const mod = o.module; |
| 7931 | 7953 | const target = mod.getTarget(); |
| 7932 | 7954 | const scalar_ty = ty.scalarType(mod); |
| 7933 | | const llvm_ty = (try o.lowerType(ty)).toLlvm(&o.builder); |
| 7934 | | const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 7955 | const llvm_ty = try o.lowerType(ty); |
| 7956 | const scalar_llvm_ty = try o.lowerType(scalar_ty); |
| 7935 | 7957 | |
| 7936 | 7958 | const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target); |
| 7937 | | var fn_name_buf: [64]u8 = undefined; |
| 7938 | 7959 | const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { |
| 7939 | 7960 | // Some operations are dedicated LLVM instructions, not available as intrinsics |
| 7940 | 7961 | .neg => return self.builder.buildFNeg(params[0], ""), |
| ... | ... | @@ -7952,7 +7973,7 @@ pub const FuncGen = struct { |
| 7952 | 7973 | .neg => { |
| 7953 | 7974 | // In this case we can generate a softfloat negation by XORing the |
| 7954 | 7975 | // bits with a constant. |
| 7955 | | const int_llvm_ty = self.context.intType(float_bits); |
| 7976 | const int_llvm_ty = (try o.builder.intType(@intCast(float_bits))).toLlvm(&o.builder); |
| 7956 | 7977 | const one = int_llvm_ty.constInt(1, .False); |
| 7957 | 7978 | const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); |
| 7958 | 7979 | const sign_mask = one.constShl(shift_amt); |
| ... | ... | @@ -7965,13 +7986,11 @@ pub const FuncGen = struct { |
| 7965 | 7986 | const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, ""); |
| 7966 | 7987 | break :blk self.builder.buildXor(bitcasted_operand, sign_mask, ""); |
| 7967 | 7988 | }; |
| 7968 | | return self.builder.buildBitCast(result, llvm_ty, ""); |
| 7969 | | }, |
| 7970 | | .add, .sub, .div, .mul => FloatOpStrat{ |
| 7971 | | .libc = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f3", .{ |
| 7972 | | @tagName(op), compilerRtFloatAbbrev(float_bits), |
| 7973 | | }) catch unreachable, |
| 7989 | return self.builder.buildBitCast(result, llvm_ty.toLlvm(&o.builder), ""); |
| 7974 | 7990 | }, |
| 7991 | .add, .sub, .div, .mul => .{ .libc = try o.builder.fmt("__{s}{s}f3", .{ |
| 7992 | @tagName(op), compilerRtFloatAbbrev(float_bits), |
| 7993 | }) }, |
| 7975 | 7994 | .ceil, |
| 7976 | 7995 | .cos, |
| 7977 | 7996 | .exp, |
| ... | ... | @@ -7990,21 +8009,22 @@ pub const FuncGen = struct { |
| 7990 | 8009 | .sqrt, |
| 7991 | 8010 | .tan, |
| 7992 | 8011 | .trunc, |
| 7993 | | => FloatOpStrat{ |
| 7994 | | .libc = std.fmt.bufPrintZ(&fn_name_buf, "{s}{s}{s}", .{ |
| 7995 | | libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), |
| 7996 | | }) catch unreachable, |
| 7997 | | }, |
| 8012 | => .{ .libc = try o.builder.fmt("{s}{s}{s}", .{ |
| 8013 | libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), |
| 8014 | }) }, |
| 7998 | 8015 | }; |
| 7999 | 8016 | }; |
| 8000 | 8017 | |
| 8001 | 8018 | const llvm_fn: *llvm.Value = switch (strat) { |
| 8002 | | .intrinsic => |fn_name| self.getIntrinsic(fn_name, &.{llvm_ty}), |
| 8019 | .intrinsic => |fn_name| try self.getIntrinsic(fn_name, &.{llvm_ty}), |
| 8003 | 8020 | .libc => |fn_name| b: { |
| 8004 | | const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty }; |
| 8005 | | const libc_fn = try self.getLibcFunction(fn_name, param_types[0..params.len], scalar_llvm_ty); |
| 8021 | const libc_fn = try self.getLibcFunction( |
| 8022 | fn_name, |
| 8023 | ([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len], |
| 8024 | scalar_llvm_ty, |
| 8025 | ); |
| 8006 | 8026 | if (ty.zigTypeTag(mod) == .Vector) { |
| 8007 | | const result = llvm_ty.getUndef(); |
| 8027 | const result = llvm_ty.toLlvm(&o.builder).getUndef(); |
| 8008 | 8028 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod)); |
| 8009 | 8029 | } |
| 8010 | 8030 | |
| ... | ... | @@ -8061,7 +8081,7 @@ pub const FuncGen = struct { |
| 8061 | 8081 | |
| 8062 | 8082 | if (isByRef(dest_ty, mod)) { |
| 8063 | 8083 | const result_alignment = dest_ty.abiAlignment(mod); |
| 8064 | | const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment); |
| 8084 | const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment); |
| 8065 | 8085 | { |
| 8066 | 8086 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 8067 | 8087 | const store_inst = self.builder.buildStore(result, field_ptr); |
| ... | ... | @@ -8266,17 +8286,15 @@ pub const FuncGen = struct { |
| 8266 | 8286 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 8267 | 8287 | return self.builder.buildFPTrunc(operand, dest_llvm_ty, ""); |
| 8268 | 8288 | } else { |
| 8269 | | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 8270 | | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 8289 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 8290 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 8271 | 8291 | |
| 8272 | | var fn_name_buf: [64]u8 = undefined; |
| 8273 | | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__trunc{s}f{s}f2", .{ |
| 8292 | const fn_name = try o.builder.fmt("__trunc{s}f{s}f2", .{ |
| 8274 | 8293 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 8275 | | }) catch unreachable; |
| 8294 | }); |
| 8276 | 8295 | |
| 8277 | 8296 | const params = [1]*llvm.Value{operand}; |
| 8278 | | const param_types = [1]*llvm.Type{operand_llvm_ty}; |
| 8279 | | const llvm_fn = try self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); |
| 8297 | const llvm_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); |
| 8280 | 8298 | |
| 8281 | 8299 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .C, .Auto, ""); |
| 8282 | 8300 | } |
| ... | ... | @@ -8297,17 +8315,15 @@ pub const FuncGen = struct { |
| 8297 | 8315 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 8298 | 8316 | return self.builder.buildFPExt(operand, dest_llvm_ty, ""); |
| 8299 | 8317 | } else { |
| 8300 | | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 8301 | | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 8318 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 8319 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 8302 | 8320 | |
| 8303 | | var fn_name_buf: [64]u8 = undefined; |
| 8304 | | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__extend{s}f{s}f2", .{ |
| 8321 | const fn_name = try o.builder.fmt("__extend{s}f{s}f2", .{ |
| 8305 | 8322 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 8306 | | }) catch unreachable; |
| 8323 | }); |
| 8307 | 8324 | |
| 8308 | 8325 | const params = [1]*llvm.Value{operand}; |
| 8309 | | const param_types = [1]*llvm.Type{operand_llvm_ty}; |
| 8310 | | const llvm_fn = try self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); |
| 8326 | const llvm_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); |
| 8311 | 8327 | |
| 8312 | 8328 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .C, .Auto, ""); |
| 8313 | 8329 | } |
| ... | ... | @@ -8358,7 +8374,7 @@ pub const FuncGen = struct { |
| 8358 | 8374 | if (!result_is_ref) { |
| 8359 | 8375 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); |
| 8360 | 8376 | } |
| 8361 | | const array_ptr = self.buildAlloca(llvm_dest_ty, null); |
| 8377 | const array_ptr = try self.buildAlloca(llvm_dest_ty, null); |
| 8362 | 8378 | const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8; |
| 8363 | 8379 | if (bitcast_ok) { |
| 8364 | 8380 | const llvm_store = self.builder.buildStore(operand, array_ptr); |
| ... | ... | @@ -8367,7 +8383,7 @@ pub const FuncGen = struct { |
| 8367 | 8383 | // If the ABI size of the element type is not evenly divisible by size in bits; |
| 8368 | 8384 | // a simple bitcast will not work, and we fall back to extractelement. |
| 8369 | 8385 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8370 | | const llvm_u32 = self.context.intType(32); |
| 8386 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 8371 | 8387 | const zero = llvm_usize.constNull(); |
| 8372 | 8388 | const vector_len = operand_ty.arrayLen(mod); |
| 8373 | 8389 | var i: u64 = 0; |
| ... | ... | @@ -8401,7 +8417,7 @@ pub const FuncGen = struct { |
| 8401 | 8417 | const array_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 8402 | 8418 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 8403 | 8419 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8404 | | const llvm_u32 = self.context.intType(32); |
| 8420 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 8405 | 8421 | const zero = llvm_usize.constNull(); |
| 8406 | 8422 | const vector_len = operand_ty.arrayLen(mod); |
| 8407 | 8423 | var vector = llvm_vector_ty.getUndef(); |
| ... | ... | @@ -8427,7 +8443,7 @@ pub const FuncGen = struct { |
| 8427 | 8443 | |
| 8428 | 8444 | if (result_is_ref) { |
| 8429 | 8445 | const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod)); |
| 8430 | | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); |
| 8446 | const result_ptr = try self.buildAlloca(llvm_dest_ty, alignment); |
| 8431 | 8447 | const store_inst = self.builder.buildStore(operand, result_ptr); |
| 8432 | 8448 | store_inst.setAlignment(alignment); |
| 8433 | 8449 | return result_ptr; |
| ... | ... | @@ -8438,7 +8454,7 @@ pub const FuncGen = struct { |
| 8438 | 8454 | // but LLVM won't let us bitcast struct values. |
| 8439 | 8455 | // Therefore, we store operand to alloca, then load for result. |
| 8440 | 8456 | const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod)); |
| 8441 | | const result_ptr = self.buildAlloca(llvm_dest_ty, alignment); |
| 8457 | const result_ptr = try self.buildAlloca(llvm_dest_ty, alignment); |
| 8442 | 8458 | const store_inst = self.builder.buildStore(operand, result_ptr); |
| 8443 | 8459 | store_inst.setAlignment(alignment); |
| 8444 | 8460 | const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); |
| ... | ... | @@ -8489,7 +8505,7 @@ pub const FuncGen = struct { |
| 8489 | 8505 | _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); |
| 8490 | 8506 | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 8491 | 8507 | const alignment = inst_ty.abiAlignment(mod); |
| 8492 | | const alloca = self.buildAlloca(arg_val.typeOf(), alignment); |
| 8508 | const alloca = try self.buildAlloca(arg_val.typeOf(), alignment); |
| 8493 | 8509 | const store_inst = self.builder.buildStore(arg_val, alloca); |
| 8494 | 8510 | store_inst.setAlignment(alignment); |
| 8495 | 8511 | _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); |
| ... | ... | @@ -8527,11 +8543,11 @@ pub const FuncGen = struct { |
| 8527 | 8543 | |
| 8528 | 8544 | /// Use this instead of builder.buildAlloca, because this function makes sure to |
| 8529 | 8545 | /// put the alloca instruction at the top of the function! |
| 8530 | | fn buildAlloca(self: *FuncGen, llvm_ty: *llvm.Type, alignment: ?c_uint) *llvm.Value { |
| 8546 | fn buildAlloca(self: *FuncGen, llvm_ty: *llvm.Type, alignment: ?c_uint) Allocator.Error!*llvm.Value { |
| 8531 | 8547 | const o = self.dg.object; |
| 8532 | 8548 | const mod = o.module; |
| 8533 | 8549 | const target = mod.getTarget(); |
| 8534 | | return buildAllocaInner(self.context, self.builder, self.llvm_func, self.di_scope != null, llvm_ty, alignment, target); |
| 8550 | return o.buildAllocaInner(self.builder, self.llvm_func, self.di_scope != null, llvm_ty, alignment, target); |
| 8535 | 8551 | } |
| 8536 | 8552 | |
| 8537 | 8553 | fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { |
| ... | ... | @@ -8547,7 +8563,7 @@ pub const FuncGen = struct { |
| 8547 | 8563 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8548 | 8564 | // extra information to LLVM. However, safety makes the difference between using |
| 8549 | 8565 | // 0xaa or actual undefined for the fill byte. |
| 8550 | | const u8_llvm_ty = self.context.intType(8); |
| 8566 | const u8_llvm_ty = Builder.Type.i8.toLlvm(&o.builder); |
| 8551 | 8567 | const fill_byte = if (safety) |
| 8552 | 8568 | u8_llvm_ty.constInt(0xaa, .False) |
| 8553 | 8569 | else |
| ... | ... | @@ -8558,7 +8574,7 @@ pub const FuncGen = struct { |
| 8558 | 8574 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8559 | 8575 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod)); |
| 8560 | 8576 | if (safety and mod.comp.bin_file.options.valgrind) { |
| 8561 | | self.valgrindMarkUndef(dest_ptr, len); |
| 8577 | try self.valgrindMarkUndef(dest_ptr, len); |
| 8562 | 8578 | } |
| 8563 | 8579 | return null; |
| 8564 | 8580 | } |
| ... | ... | @@ -8609,7 +8625,7 @@ pub const FuncGen = struct { |
| 8609 | 8625 | |
| 8610 | 8626 | fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8611 | 8627 | _ = inst; |
| 8612 | | const llvm_fn = self.getIntrinsic("llvm.trap", &.{}); |
| 8628 | const llvm_fn = try self.getIntrinsic("llvm.trap", &.{}); |
| 8613 | 8629 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .Cold, .Auto, ""); |
| 8614 | 8630 | _ = self.builder.buildUnreachable(); |
| 8615 | 8631 | return null; |
| ... | ... | @@ -8617,7 +8633,7 @@ pub const FuncGen = struct { |
| 8617 | 8633 | |
| 8618 | 8634 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8619 | 8635 | _ = inst; |
| 8620 | | const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); |
| 8636 | const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{}); |
| 8621 | 8637 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .C, .Auto, ""); |
| 8622 | 8638 | return null; |
| 8623 | 8639 | } |
| ... | ... | @@ -8633,8 +8649,8 @@ pub const FuncGen = struct { |
| 8633 | 8649 | return llvm_usize.constNull(); |
| 8634 | 8650 | } |
| 8635 | 8651 | |
| 8636 | | const llvm_i32 = self.context.intType(32); |
| 8637 | | const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); |
| 8652 | const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder); |
| 8653 | const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{}); |
| 8638 | 8654 | const params = [_]*llvm.Value{llvm_i32.constNull()}; |
| 8639 | 8655 | const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 8640 | 8656 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); |
| ... | ... | @@ -8643,16 +8659,13 @@ pub const FuncGen = struct { |
| 8643 | 8659 | fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8644 | 8660 | _ = inst; |
| 8645 | 8661 | const o = self.dg.object; |
| 8646 | | const llvm_i32 = self.context.intType(32); |
| 8647 | 8662 | const llvm_fn_name = "llvm.frameaddress.p0"; |
| 8648 | 8663 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 8649 | | const llvm_p0i8 = self.context.pointerType(0); |
| 8650 | | const param_types = [_]*llvm.Type{llvm_i32}; |
| 8651 | | const fn_type = llvm.functionType(llvm_p0i8, &param_types, param_types.len, .False); |
| 8652 | | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); |
| 8664 | const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal); |
| 8665 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 8653 | 8666 | }; |
| 8654 | 8667 | |
| 8655 | | const params = [_]*llvm.Value{llvm_i32.constNull()}; |
| 8668 | const params = [_]*llvm.Value{Builder.Type.i32.toLlvm(&o.builder).constNull()}; |
| 8656 | 8669 | const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 8657 | 8670 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8658 | 8671 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); |
| ... | ... | @@ -8841,9 +8854,8 @@ pub const FuncGen = struct { |
| 8841 | 8854 | const dest_slice = try self.resolveInst(bin_op.lhs); |
| 8842 | 8855 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 8843 | 8856 | const elem_ty = self.typeOf(bin_op.rhs); |
| 8844 | | const target = mod.getTarget(); |
| 8845 | 8857 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8846 | | const u8_llvm_ty = self.context.intType(8); |
| 8858 | const u8_llvm_ty = Builder.Type.i8.toLlvm(&o.builder); |
| 8847 | 8859 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty); |
| 8848 | 8860 | const is_volatile = ptr_ty.isVolatilePtr(mod); |
| 8849 | 8861 | |
| ... | ... | @@ -8864,7 +8876,7 @@ pub const FuncGen = struct { |
| 8864 | 8876 | u8_llvm_ty.constInt(0xaa, .False) |
| 8865 | 8877 | else |
| 8866 | 8878 | u8_llvm_ty.getUndef(); |
| 8867 | | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8879 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8868 | 8880 | if (intrinsic_len0_traps) { |
| 8869 | 8881 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8870 | 8882 | } else { |
| ... | ... | @@ -8872,7 +8884,7 @@ pub const FuncGen = struct { |
| 8872 | 8884 | } |
| 8873 | 8885 | |
| 8874 | 8886 | if (safety and mod.comp.bin_file.options.valgrind) { |
| 8875 | | self.valgrindMarkUndef(dest_ptr, len); |
| 8887 | try self.valgrindMarkUndef(dest_ptr, len); |
| 8876 | 8888 | } |
| 8877 | 8889 | return null; |
| 8878 | 8890 | } |
| ... | ... | @@ -8886,7 +8898,7 @@ pub const FuncGen = struct { |
| 8886 | 8898 | .ty = Type.u8, |
| 8887 | 8899 | .val = byte_val, |
| 8888 | 8900 | }); |
| 8889 | | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8901 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8890 | 8902 | |
| 8891 | 8903 | if (intrinsic_len0_traps) { |
| 8892 | 8904 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | ... | @@ -8903,7 +8915,7 @@ pub const FuncGen = struct { |
| 8903 | 8915 | if (elem_abi_size == 1) { |
| 8904 | 8916 | // In this case we can take advantage of LLVM's intrinsic. |
| 8905 | 8917 | const fill_byte = try self.bitCast(value, elem_ty, Type.u8); |
| 8906 | | const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8918 | const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); |
| 8907 | 8919 | |
| 8908 | 8920 | if (intrinsic_len0_traps) { |
| 8909 | 8921 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | ... | @@ -8934,7 +8946,7 @@ pub const FuncGen = struct { |
| 8934 | 8946 | const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody"); |
| 8935 | 8947 | const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd"); |
| 8936 | 8948 | |
| 8937 | | const llvm_usize_ty = self.context.intType(target.ptrBitWidth()); |
| 8949 | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8938 | 8950 | const len = switch (ptr_ty.ptrSize(mod)) { |
| 8939 | 8951 | .Slice => self.builder.buildExtractValue(dest_slice, 1, ""), |
| 8940 | 8952 | .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False), |
| ... | ... | @@ -9008,7 +9020,7 @@ pub const FuncGen = struct { |
| 9008 | 9020 | const src_slice = try self.resolveInst(bin_op.rhs); |
| 9009 | 9021 | const src_ptr_ty = self.typeOf(bin_op.rhs); |
| 9010 | 9022 | const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty); |
| 9011 | | const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); |
| 9023 | const len = try self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); |
| 9012 | 9024 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); |
| 9013 | 9025 | const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod); |
| 9014 | 9026 | |
| ... | ... | @@ -9123,9 +9135,8 @@ pub const FuncGen = struct { |
| 9123 | 9135 | const operand_ty = self.typeOf(ty_op.operand); |
| 9124 | 9136 | const operand = try self.resolveInst(ty_op.operand); |
| 9125 | 9137 | |
| 9126 | | const llvm_i1 = self.context.intType(1); |
| 9127 | | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 9128 | | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 9138 | const llvm_i1 = Builder.Type.i1.toLlvm(&o.builder); |
| 9139 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{try o.lowerType(operand_ty)}); |
| 9129 | 9140 | |
| 9130 | 9141 | const params = [_]*llvm.Value{ operand, llvm_i1.constNull() }; |
| 9131 | 9142 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); |
| ... | ... | @@ -9151,8 +9162,7 @@ pub const FuncGen = struct { |
| 9151 | 9162 | const operand = try self.resolveInst(ty_op.operand); |
| 9152 | 9163 | |
| 9153 | 9164 | const params = [_]*llvm.Value{operand}; |
| 9154 | | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 9155 | | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 9165 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{try o.lowerType(operand_ty)}); |
| 9156 | 9166 | |
| 9157 | 9167 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); |
| 9158 | 9168 | const result_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -9178,15 +9188,16 @@ pub const FuncGen = struct { |
| 9178 | 9188 | assert(bits % 8 == 0); |
| 9179 | 9189 | |
| 9180 | 9190 | var operand = try self.resolveInst(ty_op.operand); |
| 9181 | | var operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 9191 | var operand_llvm_ty = try o.lowerType(operand_ty); |
| 9182 | 9192 | |
| 9183 | 9193 | if (bits % 16 == 8) { |
| 9184 | 9194 | // If not an even byte-multiple, we need zero-extend + shift-left 1 byte |
| 9185 | 9195 | // The truncated result at the end will be the correct bswap |
| 9186 | | const scalar_llvm_ty = self.context.intType(bits + 8); |
| 9196 | const scalar_ty = try o.builder.intType(@intCast(bits + 8)); |
| 9197 | const scalar_llvm_ty = scalar_ty.toLlvm(&o.builder); |
| 9187 | 9198 | if (operand_ty.zigTypeTag(mod) == .Vector) { |
| 9188 | 9199 | const vec_len = operand_ty.vectorLen(mod); |
| 9189 | | operand_llvm_ty = scalar_llvm_ty.vectorType(vec_len); |
| 9200 | operand_llvm_ty = try o.builder.vectorType(.normal, vec_len, scalar_ty); |
| 9190 | 9201 | |
| 9191 | 9202 | const shifts = try self.gpa.alloc(*llvm.Value, vec_len); |
| 9192 | 9203 | defer self.gpa.free(shifts); |
| ... | ... | @@ -9196,18 +9207,18 @@ pub const FuncGen = struct { |
| 9196 | 9207 | } |
| 9197 | 9208 | const shift_vec = llvm.constVector(shifts.ptr, vec_len); |
| 9198 | 9209 | |
| 9199 | | const extended = self.builder.buildZExt(operand, operand_llvm_ty, ""); |
| 9210 | const extended = self.builder.buildZExt(operand, operand_llvm_ty.toLlvm(&o.builder), ""); |
| 9200 | 9211 | operand = self.builder.buildShl(extended, shift_vec, ""); |
| 9201 | 9212 | } else { |
| 9202 | 9213 | const extended = self.builder.buildZExt(operand, scalar_llvm_ty, ""); |
| 9203 | 9214 | operand = self.builder.buildShl(extended, scalar_llvm_ty.constInt(8, .False), ""); |
| 9204 | | operand_llvm_ty = scalar_llvm_ty; |
| 9215 | operand_llvm_ty = scalar_ty; |
| 9205 | 9216 | } |
| 9206 | 9217 | bits = bits + 8; |
| 9207 | 9218 | } |
| 9208 | 9219 | |
| 9209 | 9220 | const params = [_]*llvm.Value{operand}; |
| 9210 | | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 9221 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); |
| 9211 | 9222 | |
| 9212 | 9223 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); |
| 9213 | 9224 | |
| ... | ... | @@ -9252,7 +9263,7 @@ pub const FuncGen = struct { |
| 9252 | 9263 | |
| 9253 | 9264 | self.builder.positionBuilderAtEnd(end_block); |
| 9254 | 9265 | |
| 9255 | | const llvm_type = self.context.intType(1); |
| 9266 | const llvm_type = Builder.Type.i1.toLlvm(&o.builder); |
| 9256 | 9267 | const incoming_values: [2]*llvm.Value = .{ |
| 9257 | 9268 | llvm_type.constInt(1, .False), llvm_type.constInt(0, .False), |
| 9258 | 9269 | }; |
| ... | ... | @@ -9281,25 +9292,30 @@ pub const FuncGen = struct { |
| 9281 | 9292 | |
| 9282 | 9293 | // TODO: detect when the type changes and re-emit this function. |
| 9283 | 9294 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); |
| 9284 | | if (gop.found_existing) return gop.value_ptr.*; |
| 9295 | if (gop.found_existing) return gop.value_ptr.toLlvm(&o.builder); |
| 9285 | 9296 | errdefer assert(o.named_enum_map.remove(enum_type.decl)); |
| 9286 | 9297 | |
| 9287 | | var arena_allocator = std.heap.ArenaAllocator.init(self.gpa); |
| 9288 | | defer arena_allocator.deinit(); |
| 9289 | | const arena = arena_allocator.allocator(); |
| 9290 | | |
| 9291 | 9298 | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); |
| 9292 | | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}); |
| 9293 | | |
| 9294 | | const param_types = [_]*llvm.Type{(try o.lowerType(enum_type.tag_ty.toType())).toLlvm(&o.builder)}; |
| 9299 | const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{ |
| 9300 | fqn.fmt(&mod.intern_pool), |
| 9301 | }); |
| 9295 | 9302 | |
| 9296 | | const llvm_ret_ty = (try o.lowerType(Type.bool)).toLlvm(&o.builder); |
| 9297 | | const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False); |
| 9298 | | const fn_val = o.llvm_module.addFunction(llvm_fn_name, fn_type); |
| 9303 | const fn_type = try o.builder.fnType(.i1, &.{try o.lowerType( |
| 9304 | enum_type.tag_ty.toType(), |
| 9305 | )}, .normal); |
| 9306 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9299 | 9307 | fn_val.setLinkage(.Internal); |
| 9300 | 9308 | fn_val.setFunctionCallConv(.Fast); |
| 9301 | 9309 | o.addCommonFnAttributes(fn_val); |
| 9302 | | gop.value_ptr.* = fn_val; |
| 9310 | |
| 9311 | var global = Builder.Global{ |
| 9312 | .linkage = .internal, |
| 9313 | .type = fn_type, |
| 9314 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, |
| 9315 | }; |
| 9316 | var function = Builder.Function{ |
| 9317 | .global = @enumFromInt(o.builder.globals.count()), |
| 9318 | }; |
| 9303 | 9319 | |
| 9304 | 9320 | const prev_block = self.builder.getInsertBlock(); |
| 9305 | 9321 | const prev_debug_location = self.builder.getCurrentDebugLocation2(); |
| ... | ... | @@ -9330,10 +9346,15 @@ pub const FuncGen = struct { |
| 9330 | 9346 | switch_instr.addCase(this_tag_int_value, named_block); |
| 9331 | 9347 | } |
| 9332 | 9348 | self.builder.positionBuilderAtEnd(named_block); |
| 9333 | | _ = self.builder.buildRet(self.context.intType(1).constInt(1, .False)); |
| 9349 | _ = self.builder.buildRet(Builder.Type.i1.toLlvm(&o.builder).constInt(1, .False)); |
| 9334 | 9350 | |
| 9335 | 9351 | self.builder.positionBuilderAtEnd(unnamed_block); |
| 9336 | | _ = self.builder.buildRet(self.context.intType(1).constInt(0, .False)); |
| 9352 | _ = self.builder.buildRet(Builder.Type.i1.toLlvm(&o.builder).constInt(0, .False)); |
| 9353 | |
| 9354 | try o.builder.llvm_globals.append(self.gpa, fn_val); |
| 9355 | _ = try o.builder.addGlobal(llvm_fn_name, global); |
| 9356 | try o.builder.functions.append(self.gpa, function); |
| 9357 | gop.value_ptr.* = global.kind.function; |
| 9337 | 9358 | return fn_val; |
| 9338 | 9359 | } |
| 9339 | 9360 | |
| ... | ... | @@ -9361,20 +9382,22 @@ pub const FuncGen = struct { |
| 9361 | 9382 | const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); |
| 9362 | 9383 | |
| 9363 | 9384 | const slice_ty = Type.slice_const_u8_sentinel_0; |
| 9364 | | const llvm_ret_ty = (try o.lowerType(slice_ty)).toLlvm(&o.builder); |
| 9385 | const ret_ty = try o.lowerType(slice_ty); |
| 9386 | const llvm_ret_ty = ret_ty.toLlvm(&o.builder); |
| 9365 | 9387 | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 9366 | 9388 | const slice_alignment = slice_ty.abiAlignment(mod); |
| 9367 | 9389 | |
| 9368 | | const param_types = [_]*llvm.Type{(try o.lowerType(enum_type.tag_ty.toType())).toLlvm(&o.builder)}; |
| 9369 | | |
| 9370 | | const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False); |
| 9371 | | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type); |
| 9390 | const fn_type = try o.builder.fnType(ret_ty, &.{ |
| 9391 | try o.lowerType(enum_type.tag_ty.toType()), |
| 9392 | }, .normal); |
| 9393 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9372 | 9394 | fn_val.setLinkage(.Internal); |
| 9373 | 9395 | fn_val.setFunctionCallConv(.Fast); |
| 9374 | 9396 | o.addCommonFnAttributes(fn_val); |
| 9375 | 9397 | |
| 9376 | 9398 | var global = Builder.Global{ |
| 9377 | | .type = try o.builder.fnType(.void, &.{}, .normal), |
| 9399 | .linkage = .internal, |
| 9400 | .type = fn_type, |
| 9378 | 9401 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, |
| 9379 | 9402 | }; |
| 9380 | 9403 | var function = Builder.Function{ |
| ... | ... | @@ -9457,15 +9480,24 @@ pub const FuncGen = struct { |
| 9457 | 9480 | |
| 9458 | 9481 | // Function signature: fn (anyerror) bool |
| 9459 | 9482 | |
| 9460 | | const ret_llvm_ty = (try o.lowerType(Type.bool)).toLlvm(&o.builder); |
| 9461 | | const anyerror_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder); |
| 9462 | | const param_types = [_]*llvm.Type{anyerror_llvm_ty}; |
| 9483 | const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); |
| 9484 | const llvm_fn = o.llvm_module.addFunction(lt_errors_fn_name, fn_type.toLlvm(&o.builder)); |
| 9485 | |
| 9486 | var global = Builder.Global{ |
| 9487 | .type = fn_type, |
| 9488 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, |
| 9489 | }; |
| 9490 | var function = Builder.Function{ |
| 9491 | .global = @enumFromInt(o.builder.globals.count()), |
| 9492 | }; |
| 9463 | 9493 | |
| 9464 | | const fn_type = llvm.functionType(ret_llvm_ty, &param_types, param_types.len, .False); |
| 9465 | | const llvm_fn = o.llvm_module.addFunction(lt_errors_fn_name, fn_type); |
| 9466 | 9494 | llvm_fn.setLinkage(.Internal); |
| 9467 | 9495 | llvm_fn.setFunctionCallConv(.Fast); |
| 9468 | 9496 | o.addCommonFnAttributes(llvm_fn); |
| 9497 | |
| 9498 | try o.builder.llvm_globals.append(self.gpa, llvm_fn); |
| 9499 | _ = try o.builder.addGlobal(try o.builder.string(lt_errors_fn_name), global); |
| 9500 | try o.builder.functions.append(self.gpa, function); |
| 9469 | 9501 | return llvm_fn; |
| 9470 | 9502 | } |
| 9471 | 9503 | |
| ... | ... | @@ -9523,7 +9555,7 @@ pub const FuncGen = struct { |
| 9523 | 9555 | const values = try self.gpa.alloc(*llvm.Value, mask_len); |
| 9524 | 9556 | defer self.gpa.free(values); |
| 9525 | 9557 | |
| 9526 | | const llvm_i32 = self.context.intType(32); |
| 9558 | const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9527 | 9559 | |
| 9528 | 9560 | for (values, 0..) |*val, i| { |
| 9529 | 9561 | const elem = try mask.elemValue(mod, i); |
| ... | ... | @@ -9565,9 +9597,9 @@ pub const FuncGen = struct { |
| 9565 | 9597 | const llvm_result_ty = accum_init.typeOf(); |
| 9566 | 9598 | |
| 9567 | 9599 | // Allocate and initialize our mutable variables |
| 9568 | | const i_ptr = self.buildAlloca(llvm_usize_ty, null); |
| 9600 | const i_ptr = try self.buildAlloca(llvm_usize_ty, null); |
| 9569 | 9601 | _ = self.builder.buildStore(llvm_usize_ty.constInt(0, .False), i_ptr); |
| 9570 | | const accum_ptr = self.buildAlloca(llvm_result_ty, null); |
| 9602 | const accum_ptr = try self.buildAlloca(llvm_result_ty, null); |
| 9571 | 9603 | _ = self.builder.buildStore(accum_init, accum_ptr); |
| 9572 | 9604 | |
| 9573 | 9605 | // Setup the loop |
| ... | ... | @@ -9656,27 +9688,25 @@ pub const FuncGen = struct { |
| 9656 | 9688 | |
| 9657 | 9689 | // Reduction could not be performed with intrinsics. |
| 9658 | 9690 | // Use a manual loop over a softfloat call instead. |
| 9659 | | var fn_name_buf: [64]u8 = undefined; |
| 9660 | 9691 | const float_bits = scalar_ty.floatBits(target); |
| 9661 | 9692 | const fn_name = switch (reduce.operation) { |
| 9662 | | .Min => std.fmt.bufPrintZ(&fn_name_buf, "{s}fmin{s}", .{ |
| 9693 | .Min => try o.builder.fmt("{s}fmin{s}", .{ |
| 9663 | 9694 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), |
| 9664 | | }) catch unreachable, |
| 9665 | | .Max => std.fmt.bufPrintZ(&fn_name_buf, "{s}fmax{s}", .{ |
| 9695 | }), |
| 9696 | .Max => try o.builder.fmt("{s}fmax{s}", .{ |
| 9666 | 9697 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), |
| 9667 | | }) catch unreachable, |
| 9668 | | .Add => std.fmt.bufPrintZ(&fn_name_buf, "__add{s}f3", .{ |
| 9698 | }), |
| 9699 | .Add => try o.builder.fmt("__add{s}f3", .{ |
| 9669 | 9700 | compilerRtFloatAbbrev(float_bits), |
| 9670 | | }) catch unreachable, |
| 9671 | | .Mul => std.fmt.bufPrintZ(&fn_name_buf, "__mul{s}f3", .{ |
| 9701 | }), |
| 9702 | .Mul => try o.builder.fmt("__mul{s}f3", .{ |
| 9672 | 9703 | compilerRtFloatAbbrev(float_bits), |
| 9673 | | }) catch unreachable, |
| 9704 | }), |
| 9674 | 9705 | else => unreachable, |
| 9675 | 9706 | }; |
| 9676 | 9707 | |
| 9677 | | const param_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 9678 | | const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty }; |
| 9679 | | const libc_fn = try self.getLibcFunction(fn_name, &param_types, param_llvm_ty); |
| 9708 | const param_llvm_ty = try o.lowerType(scalar_ty); |
| 9709 | const libc_fn = try self.getLibcFunction(fn_name, &(.{param_llvm_ty} ** 2), param_llvm_ty); |
| 9680 | 9710 | const init_value = try o.lowerValue(.{ |
| 9681 | 9711 | .ty = scalar_ty, |
| 9682 | 9712 | .val = try mod.floatValue(scalar_ty, switch (reduce.operation) { |
| ... | ... | @@ -9701,7 +9731,7 @@ pub const FuncGen = struct { |
| 9701 | 9731 | |
| 9702 | 9732 | switch (result_ty.zigTypeTag(mod)) { |
| 9703 | 9733 | .Vector => { |
| 9704 | | const llvm_u32 = self.context.intType(32); |
| 9734 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9705 | 9735 | |
| 9706 | 9736 | var vector = llvm_result_ty.getUndef(); |
| 9707 | 9737 | for (elements, 0..) |elem, i| { |
| ... | ... | @@ -9716,7 +9746,7 @@ pub const FuncGen = struct { |
| 9716 | 9746 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 9717 | 9747 | assert(struct_obj.haveLayout()); |
| 9718 | 9748 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); |
| 9719 | | const int_llvm_ty = self.context.intType(@as(c_uint, @intCast(big_bits))); |
| 9749 | const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder); |
| 9720 | 9750 | const fields = struct_obj.fields.values(); |
| 9721 | 9751 | comptime assert(Type.packed_struct_layout_version == 2); |
| 9722 | 9752 | var running_int: *llvm.Value = int_llvm_ty.constNull(); |
| ... | ... | @@ -9727,7 +9757,7 @@ pub const FuncGen = struct { |
| 9727 | 9757 | |
| 9728 | 9758 | const non_int_val = try self.resolveInst(elem); |
| 9729 | 9759 | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); |
| 9730 | | const small_int_ty = self.context.intType(ty_bit_size); |
| 9760 | const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder); |
| 9731 | 9761 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9732 | 9762 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9733 | 9763 | else |
| ... | ... | @@ -9745,10 +9775,10 @@ pub const FuncGen = struct { |
| 9745 | 9775 | } |
| 9746 | 9776 | |
| 9747 | 9777 | if (isByRef(result_ty, mod)) { |
| 9748 | | const llvm_u32 = self.context.intType(32); |
| 9778 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9749 | 9779 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 9750 | 9780 | // even if we fully populate the fields. |
| 9751 | | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9781 | const alloca_inst = try self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9752 | 9782 | |
| 9753 | 9783 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| 9754 | 9784 | for (elements, 0..) |elem, i| { |
| ... | ... | @@ -9786,7 +9816,7 @@ pub const FuncGen = struct { |
| 9786 | 9816 | assert(isByRef(result_ty, mod)); |
| 9787 | 9817 | |
| 9788 | 9818 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 9789 | | const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9819 | const alloca_inst = try self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); |
| 9790 | 9820 | |
| 9791 | 9821 | const array_info = result_ty.arrayInfo(mod); |
| 9792 | 9822 | const elem_ptr_ty = try mod.ptrType(.{ |
| ... | ... | @@ -9834,11 +9864,11 @@ pub const FuncGen = struct { |
| 9834 | 9864 | |
| 9835 | 9865 | if (union_obj.layout == .Packed) { |
| 9836 | 9866 | const big_bits = union_ty.bitSize(mod); |
| 9837 | | const int_llvm_ty = self.context.intType(@as(c_uint, @intCast(big_bits))); |
| 9867 | const int_llvm_ty = (try o.builder.intType(@intCast(big_bits))).toLlvm(&o.builder); |
| 9838 | 9868 | const field = union_obj.fields.values()[extra.field_index]; |
| 9839 | 9869 | const non_int_val = try self.resolveInst(extra.init); |
| 9840 | 9870 | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); |
| 9841 | | const small_int_ty = self.context.intType(ty_bit_size); |
| 9871 | const small_int_ty = (try o.builder.intType(@intCast(ty_bit_size))).toLlvm(&o.builder); |
| 9842 | 9872 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9843 | 9873 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9844 | 9874 | else |
| ... | ... | @@ -9866,51 +9896,47 @@ pub const FuncGen = struct { |
| 9866 | 9896 | // necessarily match the format that we need, depending on which tag is active. |
| 9867 | 9897 | // We must construct the correct unnamed struct type here, in order to then set |
| 9868 | 9898 | // the fields appropriately. |
| 9869 | | const result_ptr = self.buildAlloca(union_llvm_ty, layout.abi_align); |
| 9899 | const result_ptr = try self.buildAlloca(union_llvm_ty, layout.abi_align); |
| 9870 | 9900 | const llvm_payload = try self.resolveInst(extra.init); |
| 9871 | 9901 | assert(union_obj.haveFieldTypes()); |
| 9872 | 9902 | const field = union_obj.fields.values()[extra.field_index]; |
| 9873 | | const field_llvm_ty = (try o.lowerType(field.ty)).toLlvm(&o.builder); |
| 9903 | const field_llvm_ty = try o.lowerType(field.ty); |
| 9874 | 9904 | const field_size = field.ty.abiSize(mod); |
| 9875 | 9905 | const field_align = field.normalAlignment(mod); |
| 9876 | 9906 | |
| 9877 | | const llvm_union_ty = t: { |
| 9878 | | const payload = p: { |
| 9907 | const llvm_union_ty = (t: { |
| 9908 | const payload_ty = p: { |
| 9879 | 9909 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 9880 | | const padding_len = @as(c_uint, @intCast(layout.payload_size)); |
| 9881 | | break :p self.context.intType(8).arrayType(padding_len); |
| 9910 | const padding_len = layout.payload_size; |
| 9911 | break :p try o.builder.arrayType(padding_len, .i8); |
| 9882 | 9912 | } |
| 9883 | 9913 | if (field_size == layout.payload_size) { |
| 9884 | 9914 | break :p field_llvm_ty; |
| 9885 | 9915 | } |
| 9886 | | const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size)); |
| 9887 | | const fields: [2]*llvm.Type = .{ |
| 9888 | | field_llvm_ty, self.context.intType(8).arrayType(padding_len), |
| 9889 | | }; |
| 9890 | | break :p self.context.structType(&fields, fields.len, .True); |
| 9916 | const padding_len = layout.payload_size - field_size; |
| 9917 | break :p try o.builder.structType(.@"packed", &.{ |
| 9918 | field_llvm_ty, try o.builder.arrayType(padding_len, .i8), |
| 9919 | }); |
| 9891 | 9920 | }; |
| 9892 | | if (layout.tag_size == 0) { |
| 9893 | | const fields: [1]*llvm.Type = .{payload}; |
| 9894 | | break :t self.context.structType(&fields, fields.len, .False); |
| 9895 | | } |
| 9896 | | const tag_llvm_ty = (try o.lowerType(union_obj.tag_ty)).toLlvm(&o.builder); |
| 9897 | | var fields: [3]*llvm.Type = undefined; |
| 9898 | | var fields_len: c_uint = 2; |
| 9921 | if (layout.tag_size == 0) break :t try o.builder.structType(.normal, &.{payload_ty}); |
| 9922 | const tag_ty = try o.lowerType(union_obj.tag_ty); |
| 9923 | var fields: [3]Builder.Type = undefined; |
| 9924 | var fields_len: usize = 2; |
| 9899 | 9925 | if (layout.tag_align >= layout.payload_align) { |
| 9900 | | fields = .{ tag_llvm_ty, payload, undefined }; |
| 9926 | fields = .{ tag_ty, payload_ty, undefined }; |
| 9901 | 9927 | } else { |
| 9902 | | fields = .{ payload, tag_llvm_ty, undefined }; |
| 9928 | fields = .{ payload_ty, tag_ty, undefined }; |
| 9903 | 9929 | } |
| 9904 | 9930 | if (layout.padding != 0) { |
| 9905 | | fields[2] = self.context.intType(8).arrayType(layout.padding); |
| 9906 | | fields_len = 3; |
| 9931 | fields[fields_len] = try o.builder.arrayType(layout.padding, .i8); |
| 9932 | fields_len += 1; |
| 9907 | 9933 | } |
| 9908 | | break :t self.context.structType(&fields, fields_len, .False); |
| 9909 | | }; |
| 9934 | break :t try o.builder.structType(.normal, fields[0..fields_len]); |
| 9935 | }).toLlvm(&o.builder); |
| 9910 | 9936 | |
| 9911 | 9937 | // Now we follow the layout as expressed above with GEP instructions to set the |
| 9912 | 9938 | // tag and the payload. |
| 9913 | | const index_type = self.context.intType(32); |
| 9939 | const index_type = Builder.Type.i32.toLlvm(&o.builder); |
| 9914 | 9940 | |
| 9915 | 9941 | const field_ptr_ty = try mod.ptrType(.{ |
| 9916 | 9942 | .child = field.ty.toIntern(), |
| ... | ... | @@ -9996,22 +10022,16 @@ pub const FuncGen = struct { |
| 9996 | 10022 | .data => {}, |
| 9997 | 10023 | } |
| 9998 | 10024 | |
| 9999 | | const llvm_ptr_u8 = self.context.pointerType(0); |
| 10000 | | const llvm_u32 = self.context.intType(32); |
| 10001 | | |
| 10002 | 10025 | const llvm_fn_name = "llvm.prefetch.p0"; |
| 10003 | 10026 | const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 10004 | 10027 | // declare void @llvm.prefetch(i8*, i32, i32, i32) |
| 10005 | | const llvm_void = self.context.voidType(); |
| 10006 | | const param_types = [_]*llvm.Type{ |
| 10007 | | llvm_ptr_u8, llvm_u32, llvm_u32, llvm_u32, |
| 10008 | | }; |
| 10009 | | const fn_type = llvm.functionType(llvm_void, &param_types, param_types.len, .False); |
| 10010 | | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); |
| 10028 | const fn_type = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal); |
| 10029 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 10011 | 10030 | }; |
| 10012 | 10031 | |
| 10013 | 10032 | const ptr = try self.resolveInst(prefetch.ptr); |
| 10014 | 10033 | |
| 10034 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10015 | 10035 | const params = [_]*llvm.Value{ |
| 10016 | 10036 | ptr, |
| 10017 | 10037 | llvm_u32.constInt(@intFromEnum(prefetch.rw), .False), |
| ... | ... | @@ -10033,7 +10053,7 @@ pub const FuncGen = struct { |
| 10033 | 10053 | } |
| 10034 | 10054 | |
| 10035 | 10055 | fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !?*llvm.Value { |
| 10036 | | const llvm_u32 = self.context.intType(32); |
| 10056 | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 10037 | 10057 | |
| 10038 | 10058 | const llvm_fn_name = switch (dimension) { |
| 10039 | 10059 | 0 => basename ++ ".x", |
| ... | ... | @@ -10043,7 +10063,7 @@ pub const FuncGen = struct { |
| 10043 | 10063 | }; |
| 10044 | 10064 | |
| 10045 | 10065 | const args: [0]*llvm.Value = .{}; |
| 10046 | | const llvm_fn = self.getIntrinsic(llvm_fn_name, &.{}); |
| 10066 | const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{}); |
| 10047 | 10067 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 10048 | 10068 | } |
| 10049 | 10069 | |
| ... | ... | @@ -10064,14 +10084,14 @@ pub const FuncGen = struct { |
| 10064 | 10084 | |
| 10065 | 10085 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 10066 | 10086 | const dimension = pl_op.payload; |
| 10067 | | const llvm_u32 = self.context.intType(32); |
| 10087 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10068 | 10088 | if (dimension >= 3) { |
| 10069 | 10089 | return llvm_u32.constInt(1, .False); |
| 10070 | 10090 | } |
| 10071 | 10091 | |
| 10072 | 10092 | // Fetch the dispatch pointer, which points to this structure: |
| 10073 | 10093 | // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913 |
| 10074 | | const llvm_fn = self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{}); |
| 10094 | const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{}); |
| 10075 | 10095 | const args: [0]*llvm.Value = .{}; |
| 10076 | 10096 | const dispatch_ptr = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 10077 | 10097 | dispatch_ptr.setAlignment(4); |
| ... | ... | @@ -10080,7 +10100,7 @@ pub const FuncGen = struct { |
| 10080 | 10100 | // Just treat the dispatch pointer as an array of u16 to keep things simple. |
| 10081 | 10101 | const offset = 2 + dimension; |
| 10082 | 10102 | const index = [_]*llvm.Value{llvm_u32.constInt(offset, .False)}; |
| 10083 | | const llvm_u16 = self.context.intType(16); |
| 10103 | const llvm_u16 = Builder.Type.i16.toLlvm(&o.builder); |
| 10084 | 10104 | const workgroup_size_ptr = self.builder.buildInBoundsGEP(llvm_u16, dispatch_ptr, &index, index.len, ""); |
| 10085 | 10105 | const workgroup_size = self.builder.buildLoad(llvm_u16, workgroup_size_ptr, ""); |
| 10086 | 10106 | workgroup_size.setAlignment(2); |
| ... | ... | @@ -10126,7 +10146,7 @@ pub const FuncGen = struct { |
| 10126 | 10146 | opt_handle: *llvm.Value, |
| 10127 | 10147 | is_by_ref: bool, |
| 10128 | 10148 | ) *llvm.Value { |
| 10129 | | const non_null_llvm_ty = self.context.intType(8); |
| 10149 | const non_null_llvm_ty = Builder.Type.i8.toLlvm(&self.dg.object.builder); |
| 10130 | 10150 | const field = b: { |
| 10131 | 10151 | if (is_by_ref) { |
| 10132 | 10152 | const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); |
| ... | ... | @@ -10180,12 +10200,12 @@ pub const FuncGen = struct { |
| 10180 | 10200 | ) !?*llvm.Value { |
| 10181 | 10201 | const o = self.dg.object; |
| 10182 | 10202 | const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder); |
| 10183 | | const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), ""); |
| 10203 | const non_null_field = self.builder.buildZExt(non_null_bit, Builder.Type.i8.toLlvm(&o.builder), ""); |
| 10184 | 10204 | const mod = o.module; |
| 10185 | 10205 | |
| 10186 | 10206 | if (isByRef(optional_ty, mod)) { |
| 10187 | 10207 | const payload_alignment = optional_ty.abiAlignment(mod); |
| 10188 | | const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment); |
| 10208 | const alloca_inst = try self.buildAlloca(optional_llvm_ty, payload_alignment); |
| 10189 | 10209 | |
| 10190 | 10210 | { |
| 10191 | 10211 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); |
| ... | ... | @@ -10233,7 +10253,7 @@ pub const FuncGen = struct { |
| 10233 | 10253 | // Offset our operand pointer by the correct number of bytes. |
| 10234 | 10254 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod); |
| 10235 | 10255 | if (byte_offset == 0) return struct_ptr; |
| 10236 | | const byte_llvm_ty = self.context.intType(8); |
| 10256 | const byte_llvm_ty = Builder.Type.i8.toLlvm(&o.builder); |
| 10237 | 10257 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10238 | 10258 | const llvm_index = llvm_usize.constInt(byte_offset, .False); |
| 10239 | 10259 | const indices: [1]*llvm.Value = .{llvm_index}; |
| ... | ... | @@ -10249,7 +10269,7 @@ pub const FuncGen = struct { |
| 10249 | 10269 | // end of the struct. Treat our struct pointer as an array of two and get |
| 10250 | 10270 | // the index to the element at index `1` to get a pointer to the end of |
| 10251 | 10271 | // the struct. |
| 10252 | | const llvm_u32 = self.context.intType(32); |
| 10272 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10253 | 10273 | const llvm_index = llvm_u32.constInt(@intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 10254 | 10274 | const indices: [1]*llvm.Value = .{llvm_index}; |
| 10255 | 10275 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); |
| ... | ... | @@ -10268,11 +10288,14 @@ pub const FuncGen = struct { |
| 10268 | 10288 | } |
| 10269 | 10289 | } |
| 10270 | 10290 | |
| 10271 | | fn getIntrinsic(fg: *FuncGen, name: []const u8, types: []const *llvm.Type) *llvm.Value { |
| 10291 | fn getIntrinsic(fg: *FuncGen, name: []const u8, types: []const Builder.Type) Allocator.Error!*llvm.Value { |
| 10292 | const o = fg.dg.object; |
| 10272 | 10293 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); |
| 10273 | 10294 | assert(id != 0); |
| 10274 | | const o = fg.dg.object; |
| 10275 | | return o.llvm_module.getIntrinsicDeclaration(id, types.ptr, types.len); |
| 10295 | const llvm_types = try o.gpa.alloc(*llvm.Type, types.len); |
| 10296 | defer o.gpa.free(llvm_types); |
| 10297 | for (llvm_types, types) |*llvm_type, ty| llvm_type.* = ty.toLlvm(&o.builder); |
| 10298 | return o.llvm_module.getIntrinsicDeclaration(id, llvm_types.ptr, llvm_types.len); |
| 10276 | 10299 | } |
| 10277 | 10300 | |
| 10278 | 10301 | /// Load a by-ref type by constructing a new alloca and performing a memcpy. |
| ... | ... | @@ -10287,8 +10310,8 @@ pub const FuncGen = struct { |
| 10287 | 10310 | const mod = o.module; |
| 10288 | 10311 | const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder); |
| 10289 | 10312 | const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod)); |
| 10290 | | const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align); |
| 10291 | | const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits); |
| 10313 | const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); |
| 10314 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10292 | 10315 | const size_bytes = pointee_type.abiSize(mod); |
| 10293 | 10316 | _ = fg.builder.buildMemCpy( |
| 10294 | 10317 | result_ptr, |
| ... | ... | @@ -10317,7 +10340,7 @@ pub const FuncGen = struct { |
| 10317 | 10340 | |
| 10318 | 10341 | assert(info.flags.vector_index != .runtime); |
| 10319 | 10342 | if (info.flags.vector_index != .none) { |
| 10320 | | const index_u32 = self.context.intType(32).constInt(@intFromEnum(info.flags.vector_index), .False); |
| 10343 | const index_u32 = Builder.Type.i32.toLlvm(&o.builder).constInt(@intFromEnum(info.flags.vector_index), .False); |
| 10321 | 10344 | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 10322 | 10345 | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); |
| 10323 | 10346 | |
| ... | ... | @@ -10339,7 +10362,7 @@ pub const FuncGen = struct { |
| 10339 | 10362 | return llvm_inst; |
| 10340 | 10363 | } |
| 10341 | 10364 | |
| 10342 | | const int_elem_ty = self.context.intType(info.packed_offset.host_size * 8); |
| 10365 | const int_elem_ty = (try o.builder.intType(@intCast(info.packed_offset.host_size * 8))).toLlvm(&o.builder); |
| 10343 | 10366 | const containing_int = self.builder.buildLoad(int_elem_ty, ptr, ""); |
| 10344 | 10367 | containing_int.setAlignment(ptr_alignment); |
| 10345 | 10368 | containing_int.setVolatile(ptr_volatile); |
| ... | ... | @@ -10351,9 +10374,9 @@ pub const FuncGen = struct { |
| 10351 | 10374 | |
| 10352 | 10375 | if (isByRef(elem_ty, mod)) { |
| 10353 | 10376 | const result_align = elem_ty.abiAlignment(mod); |
| 10354 | | const result_ptr = self.buildAlloca(elem_llvm_ty, result_align); |
| 10377 | const result_ptr = try self.buildAlloca(elem_llvm_ty, result_align); |
| 10355 | 10378 | |
| 10356 | | const same_size_int = self.context.intType(elem_bits); |
| 10379 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 10357 | 10380 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 10358 | 10381 | const store_inst = self.builder.buildStore(truncated_int, result_ptr); |
| 10359 | 10382 | store_inst.setAlignment(result_align); |
| ... | ... | @@ -10361,13 +10384,13 @@ pub const FuncGen = struct { |
| 10361 | 10384 | } |
| 10362 | 10385 | |
| 10363 | 10386 | if (elem_ty.zigTypeTag(mod) == .Float or elem_ty.zigTypeTag(mod) == .Vector) { |
| 10364 | | const same_size_int = self.context.intType(elem_bits); |
| 10387 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 10365 | 10388 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 10366 | 10389 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 10367 | 10390 | } |
| 10368 | 10391 | |
| 10369 | 10392 | if (elem_ty.isPtrAtRuntime(mod)) { |
| 10370 | | const same_size_int = self.context.intType(elem_bits); |
| 10393 | const same_size_int = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 10371 | 10394 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 10372 | 10395 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 10373 | 10396 | } |
| ... | ... | @@ -10394,7 +10417,7 @@ pub const FuncGen = struct { |
| 10394 | 10417 | |
| 10395 | 10418 | assert(info.flags.vector_index != .runtime); |
| 10396 | 10419 | if (info.flags.vector_index != .none) { |
| 10397 | | const index_u32 = self.context.intType(32).constInt(@intFromEnum(info.flags.vector_index), .False); |
| 10420 | const index_u32 = Builder.Type.i32.toLlvm(&o.builder).constInt(@intFromEnum(info.flags.vector_index), .False); |
| 10398 | 10421 | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 10399 | 10422 | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); |
| 10400 | 10423 | |
| ... | ... | @@ -10412,7 +10435,7 @@ pub const FuncGen = struct { |
| 10412 | 10435 | } |
| 10413 | 10436 | |
| 10414 | 10437 | if (info.packed_offset.host_size != 0) { |
| 10415 | | const int_elem_ty = self.context.intType(info.packed_offset.host_size * 8); |
| 10438 | const int_elem_ty = (try o.builder.intType(@intCast(info.packed_offset.host_size * 8))).toLlvm(&o.builder); |
| 10416 | 10439 | const containing_int = self.builder.buildLoad(int_elem_ty, ptr, ""); |
| 10417 | 10440 | assert(ordering == .NotAtomic); |
| 10418 | 10441 | containing_int.setAlignment(ptr_alignment); |
| ... | ... | @@ -10422,7 +10445,7 @@ pub const FuncGen = struct { |
| 10422 | 10445 | const shift_amt = containing_int_ty.constInt(info.packed_offset.bit_offset, .False); |
| 10423 | 10446 | // Convert to equally-sized integer type in order to perform the bit |
| 10424 | 10447 | // operations on the value to store |
| 10425 | | const value_bits_type = self.context.intType(elem_bits); |
| 10448 | const value_bits_type = (try o.builder.intType(@intCast(elem_bits))).toLlvm(&o.builder); |
| 10426 | 10449 | const value_bits = if (elem_ty.isPtrAtRuntime(mod)) |
| 10427 | 10450 | self.builder.buildPtrToInt(elem, value_bits_type, "") |
| 10428 | 10451 | else |
| ... | ... | @@ -10458,20 +10481,19 @@ pub const FuncGen = struct { |
| 10458 | 10481 | ptr_alignment, |
| 10459 | 10482 | elem, |
| 10460 | 10483 | elem_ty.abiAlignment(mod), |
| 10461 | | self.context.intType(Type.usize.intInfo(mod).bits).constInt(size_bytes, .False), |
| 10484 | (try o.lowerType(Type.usize)).toLlvm(&o.builder).constInt(size_bytes, .False), |
| 10462 | 10485 | info.flags.is_volatile, |
| 10463 | 10486 | ); |
| 10464 | 10487 | } |
| 10465 | 10488 | |
| 10466 | | fn valgrindMarkUndef(fg: *FuncGen, ptr: *llvm.Value, len: *llvm.Value) void { |
| 10489 | fn valgrindMarkUndef(fg: *FuncGen, ptr: *llvm.Value, len: *llvm.Value) Allocator.Error!void { |
| 10467 | 10490 | const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; |
| 10468 | 10491 | const o = fg.dg.object; |
| 10469 | | const target = o.module.getTarget(); |
| 10470 | | const usize_llvm_ty = fg.context.intType(target.ptrBitWidth()); |
| 10492 | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10471 | 10493 | const zero = usize_llvm_ty.constInt(0, .False); |
| 10472 | 10494 | const req = usize_llvm_ty.constInt(VG_USERREQ__MAKE_MEM_UNDEFINED, .False); |
| 10473 | 10495 | const ptr_as_usize = fg.builder.buildPtrToInt(ptr, usize_llvm_ty, ""); |
| 10474 | | _ = valgrindClientRequest(fg, zero, req, ptr_as_usize, len, zero, zero, zero); |
| 10496 | _ = try valgrindClientRequest(fg, zero, req, ptr_as_usize, len, zero, zero, zero); |
| 10475 | 10497 | } |
| 10476 | 10498 | |
| 10477 | 10499 | fn valgrindClientRequest( |
| ... | ... | @@ -10483,18 +10505,19 @@ pub const FuncGen = struct { |
| 10483 | 10505 | a3: *llvm.Value, |
| 10484 | 10506 | a4: *llvm.Value, |
| 10485 | 10507 | a5: *llvm.Value, |
| 10486 | | ) *llvm.Value { |
| 10508 | ) Allocator.Error!*llvm.Value { |
| 10487 | 10509 | const o = fg.dg.object; |
| 10488 | 10510 | const mod = o.module; |
| 10489 | 10511 | const target = mod.getTarget(); |
| 10490 | 10512 | if (!target_util.hasValgrindSupport(target)) return default_value; |
| 10491 | 10513 | |
| 10492 | | const usize_llvm_ty = fg.context.intType(target.ptrBitWidth()); |
| 10514 | const usize_ty = try o.lowerType(Type.usize); |
| 10515 | const usize_llvm_ty = usize_ty.toLlvm(&o.builder); |
| 10493 | 10516 | const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod))); |
| 10494 | 10517 | |
| 10495 | 10518 | const array_llvm_ty = usize_llvm_ty.arrayType(6); |
| 10496 | 10519 | const array_ptr = fg.valgrind_client_request_array orelse a: { |
| 10497 | | const array_ptr = fg.buildAlloca(array_llvm_ty, usize_alignment); |
| 10520 | const array_ptr = try fg.buildAlloca(array_llvm_ty, usize_alignment); |
| 10498 | 10521 | fg.valgrind_client_request_array = array_ptr; |
| 10499 | 10522 | break :a array_ptr; |
| 10500 | 10523 | }; |
| ... | ... | @@ -10540,10 +10563,9 @@ pub const FuncGen = struct { |
| 10540 | 10563 | else => unreachable, |
| 10541 | 10564 | }; |
| 10542 | 10565 | |
| 10566 | const fn_llvm_ty = (try o.builder.fnType(usize_ty, &(.{usize_ty} ** 2), .normal)).toLlvm(&o.builder); |
| 10543 | 10567 | const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, ""); |
| 10544 | 10568 | const args = [_]*llvm.Value{ array_ptr_as_usize, default_value }; |
| 10545 | | const param_types = [_]*llvm.Type{ usize_llvm_ty, usize_llvm_ty }; |
| 10546 | | const fn_llvm_ty = llvm.functionType(usize_llvm_ty, &param_types, args.len, .False); |
| 10547 | 10569 | const asm_fn = llvm.getInlineAsm( |
| 10548 | 10570 | fn_llvm_ty, |
| 10549 | 10571 | arch_specific.template.ptr, |
| ... | ... | @@ -11200,7 +11222,6 @@ const ParamTypeIterator = struct { |
| 11200 | 11222 | llvm_index: u32, |
| 11201 | 11223 | types_len: u32, |
| 11202 | 11224 | types_buffer: [8]Builder.Type, |
| 11203 | | llvm_types_buffer: [8]*llvm.Type, |
| 11204 | 11225 | byval_attr: bool, |
| 11205 | 11226 | |
| 11206 | 11227 | const Lowering = union(enum) { |
| ... | ... | @@ -11298,7 +11319,6 @@ const ParamTypeIterator = struct { |
| 11298 | 11319 | .integer => { |
| 11299 | 11320 | it.types_len = 1; |
| 11300 | 11321 | it.types_buffer[0] = .i64; |
| 11301 | | it.llvm_types_buffer[0] = it.types_buffer[0].toLlvm(&it.object.builder); |
| 11302 | 11322 | return .multiple_llvm_types; |
| 11303 | 11323 | }, |
| 11304 | 11324 | .double_integer => return Lowering{ .i64_array = 2 }, |
| ... | ... | @@ -11408,31 +11428,22 @@ const ParamTypeIterator = struct { |
| 11408 | 11428 | } |
| 11409 | 11429 | var types_index: u32 = 0; |
| 11410 | 11430 | var types_buffer: [8]Builder.Type = undefined; |
| 11411 | | var llvm_types_buffer: [8]*llvm.Type = undefined; |
| 11412 | 11431 | for (classes) |class| { |
| 11413 | 11432 | switch (class) { |
| 11414 | 11433 | .integer => { |
| 11415 | 11434 | types_buffer[types_index] = .i64; |
| 11416 | | llvm_types_buffer[types_index] = |
| 11417 | | types_buffer[types_index].toLlvm(&it.object.builder); |
| 11418 | 11435 | types_index += 1; |
| 11419 | 11436 | }, |
| 11420 | 11437 | .sse, .sseup => { |
| 11421 | 11438 | types_buffer[types_index] = .double; |
| 11422 | | llvm_types_buffer[types_index] = |
| 11423 | | types_buffer[types_index].toLlvm(&it.object.builder); |
| 11424 | 11439 | types_index += 1; |
| 11425 | 11440 | }, |
| 11426 | 11441 | .float => { |
| 11427 | 11442 | types_buffer[types_index] = .float; |
| 11428 | | llvm_types_buffer[types_index] = |
| 11429 | | types_buffer[types_index].toLlvm(&it.object.builder); |
| 11430 | 11443 | types_index += 1; |
| 11431 | 11444 | }, |
| 11432 | 11445 | .float_combine => { |
| 11433 | 11446 | types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); |
| 11434 | | llvm_types_buffer[types_index] = |
| 11435 | | types_buffer[types_index].toLlvm(&it.object.builder); |
| 11436 | 11447 | types_index += 1; |
| 11437 | 11448 | }, |
| 11438 | 11449 | .x87 => { |
| ... | ... | @@ -11457,7 +11468,6 @@ const ParamTypeIterator = struct { |
| 11457 | 11468 | } |
| 11458 | 11469 | it.types_len = types_index; |
| 11459 | 11470 | it.types_buffer = types_buffer; |
| 11460 | | it.llvm_types_buffer = llvm_types_buffer; |
| 11461 | 11471 | it.llvm_index += types_index; |
| 11462 | 11472 | it.zig_index += 1; |
| 11463 | 11473 | return .multiple_llvm_types; |
| ... | ... | @@ -11472,7 +11482,6 @@ fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTyp |
| 11472 | 11482 | .llvm_index = 0, |
| 11473 | 11483 | .types_len = 0, |
| 11474 | 11484 | .types_buffer = undefined, |
| 11475 | | .llvm_types_buffer = undefined, |
| 11476 | 11485 | .byval_attr = false, |
| 11477 | 11486 | }; |
| 11478 | 11487 | } |
| ... | ... | @@ -11740,51 +11749,6 @@ fn compilerRtIntBits(bits: u16) u16 { |
| 11740 | 11749 | return bits; |
| 11741 | 11750 | } |
| 11742 | 11751 | |
| 11743 | | fn buildAllocaInner( |
| 11744 | | context: *llvm.Context, |
| 11745 | | builder: *llvm.Builder, |
| 11746 | | llvm_func: *llvm.Value, |
| 11747 | | di_scope_non_null: bool, |
| 11748 | | llvm_ty: *llvm.Type, |
| 11749 | | maybe_alignment: ?c_uint, |
| 11750 | | target: std.Target, |
| 11751 | | ) *llvm.Value { |
| 11752 | | const address_space = llvmAllocaAddressSpace(target); |
| 11753 | | |
| 11754 | | const alloca = blk: { |
| 11755 | | const prev_block = builder.getInsertBlock(); |
| 11756 | | const prev_debug_location = builder.getCurrentDebugLocation2(); |
| 11757 | | defer { |
| 11758 | | builder.positionBuilderAtEnd(prev_block); |
| 11759 | | if (di_scope_non_null) { |
| 11760 | | builder.setCurrentDebugLocation2(prev_debug_location); |
| 11761 | | } |
| 11762 | | } |
| 11763 | | |
| 11764 | | const entry_block = llvm_func.getFirstBasicBlock().?; |
| 11765 | | if (entry_block.getFirstInstruction()) |first_inst| { |
| 11766 | | builder.positionBuilder(entry_block, first_inst); |
| 11767 | | } else { |
| 11768 | | builder.positionBuilderAtEnd(entry_block); |
| 11769 | | } |
| 11770 | | builder.clearCurrentDebugLocation(); |
| 11771 | | |
| 11772 | | break :blk builder.buildAllocaInAddressSpace(llvm_ty, @intFromEnum(address_space), ""); |
| 11773 | | }; |
| 11774 | | |
| 11775 | | if (maybe_alignment) |alignment| { |
| 11776 | | alloca.setAlignment(alignment); |
| 11777 | | } |
| 11778 | | |
| 11779 | | // The pointer returned from this function should have the generic address space, |
| 11780 | | // if this isn't the case then cast it to the generic address space. |
| 11781 | | if (address_space != .default) { |
| 11782 | | return builder.buildAddrSpaceCast(alloca, context.pointerType(llvm.address_space.default), ""); |
| 11783 | | } |
| 11784 | | |
| 11785 | | return alloca; |
| 11786 | | } |
| 11787 | | |
| 11788 | 11752 | fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 { |
| 11789 | 11753 | return @intFromBool(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod)); |
| 11790 | 11754 | } |