| ... | @@ -569,7 +569,7 @@ pub const Object = struct { | ... | @@ -569,7 +569,7 @@ pub const Object = struct { |
| 569 | /// Therefore, this table keeps track of the mapping. | 569 | /// Therefore, this table keeps track of the mapping. |
| 570 | decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Global.Index), | 570 | decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Global.Index), |
| 571 | /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction. | 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 | /// Maps Zig types to LLVM types. The table memory is backed by the GPA of | 573 | /// Maps Zig types to LLVM types. The table memory is backed by the GPA of |
| 574 | /// the compiler. | 574 | /// the compiler. |
| 575 | /// TODO when InternPool garbage collection is implemented, this map needs | 575 | /// TODO when InternPool garbage collection is implemented, this map needs |
| ... | @@ -1210,7 +1210,7 @@ pub const Object = struct { | ... | @@ -1210,7 +1210,7 @@ pub const Object = struct { |
| 1210 | if (isByRef(param_ty, mod)) { | 1210 | if (isByRef(param_ty, mod)) { |
| 1211 | const alignment = param_ty.abiAlignment(mod); | 1211 | const alignment = param_ty.abiAlignment(mod); |
| 1212 | const param_llvm_ty = param.typeOf(); | 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 | const store_inst = builder.buildStore(param, arg_ptr); | 1214 | const store_inst = builder.buildStore(param, arg_ptr); |
| 1215 | store_inst.setAlignment(alignment); | 1215 | store_inst.setAlignment(alignment); |
| 1216 | args.appendAssumeCapacity(arg_ptr); | 1216 | args.appendAssumeCapacity(arg_ptr); |
| ... | @@ -1267,12 +1267,12 @@ pub const Object = struct { | ... | @@ -1267,12 +1267,12 @@ pub const Object = struct { |
| 1267 | | 1267 | |
| 1268 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); | 1268 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); |
| 1269 | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); | 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 | const alignment = @max( | 1271 | const alignment = @max( |
| 1272 | param_ty.abiAlignment(mod), | 1272 | param_ty.abiAlignment(mod), |
| 1273 | o.target_data.abiAlignmentOfType(int_llvm_ty), | 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 | const store_inst = builder.buildStore(param, arg_ptr); | 1276 | const store_inst = builder.buildStore(param, arg_ptr); |
| 1277 | store_inst.setAlignment(alignment); | 1277 | store_inst.setAlignment(alignment); |
| 1278 | | 1278 | |
| ... | @@ -1317,13 +1317,13 @@ pub const Object = struct { | ... | @@ -1317,13 +1317,13 @@ pub const Object = struct { |
| 1317 | }, | 1317 | }, |
| 1318 | .multiple_llvm_types => { | 1318 | .multiple_llvm_types => { |
| 1319 | assert(!it.byval_attr); | 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 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); | 1321 | const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType(); |
| 1322 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); | 1322 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); |
| 1323 | const param_alignment = param_ty.abiAlignment(mod); | 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); | 1324 | const arg_ptr = try o.buildAllocaInner(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); | 1325 | const llvm_ty = (try o.builder.structType(.normal, field_types)).toLlvm(&o.builder); |
| 1326 | for (field_types, 0..) |_, field_i_usize| { | 1326 | for (0..field_types.len) |field_i_usize| { |
| 1327 | const field_i = @as(c_uint, @intCast(field_i_usize)); | 1327 | const field_i = @as(c_uint, @intCast(field_i_usize)); |
| 1328 | const param = llvm_func.getParam(llvm_arg_i); | 1328 | const param = llvm_func.getParam(llvm_arg_i); |
| 1329 | llvm_arg_i += 1; | 1329 | llvm_arg_i += 1; |
| ... | @@ -1344,7 +1344,7 @@ pub const Object = struct { | ... | @@ -1344,7 +1344,7 @@ pub const Object = struct { |
| 1344 | assert(!it.byval_attr); | 1344 | assert(!it.byval_attr); |
| 1345 | const param = llvm_func.getParam(llvm_arg_i); | 1345 | const param = llvm_func.getParam(llvm_arg_i); |
| 1346 | llvm_arg_i += 1; | 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 | try args.ensureUnusedCapacity(1); | 1348 | try args.ensureUnusedCapacity(1); |
| 1349 | args.appendAssumeCapacity(casted); | 1349 | args.appendAssumeCapacity(casted); |
| 1350 | }, | 1350 | }, |
| ... | @@ -1355,7 +1355,7 @@ pub const Object = struct { | ... | @@ -1355,7 +1355,7 @@ pub const Object = struct { |
| 1355 | llvm_arg_i += 1; | 1355 | llvm_arg_i += 1; |
| 1356 | | 1356 | |
| 1357 | const alignment = param_ty.abiAlignment(mod); | 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 | _ = builder.buildStore(param, arg_ptr); | 1359 | _ = builder.buildStore(param, arg_ptr); |
| 1360 | | 1360 | |
| 1361 | if (isByRef(param_ty, mod)) { | 1361 | if (isByRef(param_ty, mod)) { |
| ... | @@ -1373,7 +1373,7 @@ pub const Object = struct { | ... | @@ -1373,7 +1373,7 @@ pub const Object = struct { |
| 1373 | llvm_arg_i += 1; | 1373 | llvm_arg_i += 1; |
| 1374 | | 1374 | |
| 1375 | const alignment = param_ty.abiAlignment(mod); | 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 | _ = builder.buildStore(param, arg_ptr); | 1377 | _ = builder.buildStore(param, arg_ptr); |
| 1378 | | 1378 | |
| 1379 | if (isByRef(param_ty, mod)) { | 1379 | if (isByRef(param_ty, mod)) { |
| ... | @@ -3563,7 +3563,7 @@ pub const Object = struct { | ... | @@ -3563,7 +3563,7 @@ pub const Object = struct { |
| 3563 | const bigint = int_val.toBigInt(&bigint_space, mod); | 3563 | const bigint = int_val.toBigInt(&bigint_space, mod); |
| 3564 | | 3564 | |
| 3565 | const int_info = tv.ty.intInfo(mod); | 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 | const unsigned_val = v: { | 3568 | const unsigned_val = v: { |
| 3569 | if (bigint.limbs.len == 1) { | 3569 | if (bigint.limbs.len == 1) { |
| ... | @@ -3587,26 +3587,26 @@ pub const Object = struct { | ... | @@ -3587,26 +3587,26 @@ pub const Object = struct { |
| 3587 | switch (tv.ty.floatBits(target)) { | 3587 | switch (tv.ty.floatBits(target)) { |
| 3588 | 16 => { | 3588 | 16 => { |
| 3589 | const repr = @as(u16, @bitCast(tv.val.toFloat(f16, mod))); | 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 | const int = llvm_i16.constInt(repr, .False); | 3591 | const int = llvm_i16.constInt(repr, .False); |
| 3592 | return int.constBitCast(llvm_ty); | 3592 | return int.constBitCast(llvm_ty); |
| 3593 | }, | 3593 | }, |
| 3594 | 32 => { | 3594 | 32 => { |
| 3595 | const repr = @as(u32, @bitCast(tv.val.toFloat(f32, mod))); | 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 | const int = llvm_i32.constInt(repr, .False); | 3597 | const int = llvm_i32.constInt(repr, .False); |
| 3598 | return int.constBitCast(llvm_ty); | 3598 | return int.constBitCast(llvm_ty); |
| 3599 | }, | 3599 | }, |
| 3600 | 64 => { | 3600 | 64 => { |
| 3601 | const repr = @as(u64, @bitCast(tv.val.toFloat(f64, mod))); | 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 | const int = llvm_i64.constInt(repr, .False); | 3603 | const int = llvm_i64.constInt(repr, .False); |
| 3604 | return int.constBitCast(llvm_ty); | 3604 | return int.constBitCast(llvm_ty); |
| 3605 | }, | 3605 | }, |
| 3606 | 80 => { | 3606 | 80 => { |
| 3607 | const float = tv.val.toFloat(f80, mod); | 3607 | const float = tv.val.toFloat(f80, mod); |
| 3608 | const repr = std.math.break_f80(float); | 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 | var x = llvm_i80.constInt(repr.exp, .False); | 3610 | var x = llvm_i80.constInt(repr.exp, .False); |
| 3611 | x = x.constShl(llvm_i80.constInt(64, .False)); | 3611 | x = x.constShl(llvm_i80.constInt(64, .False)); |
| 3612 | x = x.constOr(llvm_i80.constInt(repr.fraction, .False)); | 3612 | x = x.constOr(llvm_i80.constInt(repr.fraction, .False)); |
| ... | @@ -3623,7 +3623,7 @@ pub const Object = struct { | ... | @@ -3623,7 +3623,7 @@ pub const Object = struct { |
| 3623 | if (native_endian == .Big) { | 3623 | if (native_endian == .Big) { |
| 3624 | std.mem.swap(u64, &buf[0], &buf[1]); | 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 | return int.constBitCast(llvm_ty); | 3627 | return int.constBitCast(llvm_ty); |
| 3628 | }, | 3628 | }, |
| 3629 | else => unreachable, | 3629 | else => unreachable, |
| ... | @@ -3660,7 +3660,7 @@ pub const Object = struct { | ... | @@ -3660,7 +3660,7 @@ pub const Object = struct { |
| 3660 | comptime assert(optional_layout_version == 3); | 3660 | comptime assert(optional_layout_version == 3); |
| 3661 | const payload_ty = tv.ty.optionalChild(mod); | 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 | const non_null_bit = switch (opt.val) { | 3664 | const non_null_bit = switch (opt.val) { |
| 3665 | .none => llvm_i8.constNull(), | 3665 | .none => llvm_i8.constNull(), |
| 3666 | else => llvm_i8.constInt(1, .False), | 3666 | else => llvm_i8.constInt(1, .False), |
| ... | @@ -3761,7 +3761,7 @@ pub const Object = struct { | ... | @@ -3761,7 +3761,7 @@ pub const Object = struct { |
| 3761 | const elem_ty = vector_type.child.toType(); | 3761 | const elem_ty = vector_type.child.toType(); |
| 3762 | const llvm_elems = try gpa.alloc(*llvm.Value, vector_type.len); | 3762 | const llvm_elems = try gpa.alloc(*llvm.Value, vector_type.len); |
| 3763 | defer gpa.free(llvm_elems); | 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 | for (llvm_elems, 0..) |*llvm_elem, i| { | 3765 | for (llvm_elems, 0..) |*llvm_elem, i| { |
| 3766 | llvm_elem.* = switch (aggregate.storage) { | 3766 | llvm_elem.* = switch (aggregate.storage) { |
| 3767 | .bytes => |bytes| llvm_i8.constInt(bytes[i], .False), | 3767 | .bytes => |bytes| llvm_i8.constInt(bytes[i], .False), |
| ... | @@ -3802,7 +3802,7 @@ pub const Object = struct { | ... | @@ -3802,7 +3802,7 @@ pub const Object = struct { |
| 3802 | | 3802 | |
| 3803 | const padding_len = offset - prev_offset; | 3803 | const padding_len = offset - prev_offset; |
| 3804 | if (padding_len > 0) { | 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 | // TODO make this and all other padding elsewhere in debug | 3806 | // TODO make this and all other padding elsewhere in debug |
| 3807 | // builds be 0xaa not undef. | 3807 | // builds be 0xaa not undef. |
| 3808 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); | 3808 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| ... | @@ -3824,7 +3824,7 @@ pub const Object = struct { | ... | @@ -3824,7 +3824,7 @@ pub const Object = struct { |
| 3824 | offset = std.mem.alignForward(u64, offset, big_align); | 3824 | offset = std.mem.alignForward(u64, offset, big_align); |
| 3825 | const padding_len = offset - prev_offset; | 3825 | const padding_len = offset - prev_offset; |
| 3826 | if (padding_len > 0) { | 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 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); | 3828 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3829 | } | 3829 | } |
| 3830 | } | 3830 | } |
| ... | @@ -3850,7 +3850,7 @@ pub const Object = struct { | ... | @@ -3850,7 +3850,7 @@ pub const Object = struct { |
| 3850 | if (struct_obj.layout == .Packed) { | 3850 | if (struct_obj.layout == .Packed) { |
| 3851 | assert(struct_obj.haveLayout()); | 3851 | assert(struct_obj.haveLayout()); |
| 3852 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); | 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 | const fields = struct_obj.fields.values(); | 3854 | const fields = struct_obj.fields.values(); |
| 3855 | comptime assert(Type.packed_struct_layout_version == 2); | 3855 | comptime assert(Type.packed_struct_layout_version == 2); |
| 3856 | var running_int: *llvm.Value = int_llvm_ty.constNull(); | 3856 | var running_int: *llvm.Value = int_llvm_ty.constNull(); |
| ... | @@ -3863,7 +3863,7 @@ pub const Object = struct { | ... | @@ -3863,7 +3863,7 @@ pub const Object = struct { |
| 3863 | .val = try tv.val.fieldValue(mod, i), | 3863 | .val = try tv.val.fieldValue(mod, i), |
| 3864 | }); | 3864 | }); |
| 3865 | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); | 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 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) | 3867 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 3868 | non_int_val.constPtrToInt(small_int_ty) | 3868 | non_int_val.constPtrToInt(small_int_ty) |
| 3869 | else | 3869 | else |
| ... | @@ -3899,7 +3899,7 @@ pub const Object = struct { | ... | @@ -3899,7 +3899,7 @@ pub const Object = struct { |
| 3899 | | 3899 | |
| 3900 | const padding_len = offset - prev_offset; | 3900 | const padding_len = offset - prev_offset; |
| 3901 | if (padding_len > 0) { | 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 | // TODO make this and all other padding elsewhere in debug | 3903 | // TODO make this and all other padding elsewhere in debug |
| 3904 | // builds be 0xaa not undef. | 3904 | // builds be 0xaa not undef. |
| 3905 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); | 3905 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| ... | @@ -3921,7 +3921,7 @@ pub const Object = struct { | ... | @@ -3921,7 +3921,7 @@ pub const Object = struct { |
| 3921 | offset = std.mem.alignForward(u64, offset, big_align); | 3921 | offset = std.mem.alignForward(u64, offset, big_align); |
| 3922 | const padding_len = offset - prev_offset; | 3922 | const padding_len = offset - prev_offset; |
| 3923 | if (padding_len > 0) { | 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 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); | 3925 | llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); |
| 3926 | } | 3926 | } |
| 3927 | } | 3927 | } |
| ... | @@ -3969,7 +3969,7 @@ pub const Object = struct { | ... | @@ -3969,7 +3969,7 @@ pub const Object = struct { |
| 3969 | return llvm_union_ty.constNull(); | 3969 | return llvm_union_ty.constNull(); |
| 3970 | const non_int_val = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); | 3970 | const non_int_val = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3971 | const ty_bit_size = @as(u16, @intCast(field_ty.bitSize(mod))); | 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 | const small_int_val = if (field_ty.isPtrAtRuntime(mod)) | 3973 | const small_int_val = if (field_ty.isPtrAtRuntime(mod)) |
| 3974 | non_int_val.constPtrToInt(small_int_ty) | 3974 | non_int_val.constPtrToInt(small_int_ty) |
| 3975 | else | 3975 | else |
| ... | @@ -3985,7 +3985,7 @@ pub const Object = struct { | ... | @@ -3985,7 +3985,7 @@ pub const Object = struct { |
| 3985 | const payload = p: { | 3985 | const payload = p: { |
| 3986 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3986 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3987 | const padding_len = @as(c_uint, @intCast(layout.payload_size)); | 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 | const field = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); | 3990 | const field = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3991 | need_unnamed = need_unnamed or o.isUnnamedType(field_ty, field); | 3991 | need_unnamed = need_unnamed or o.isUnnamedType(field_ty, field); |
| ... | @@ -3995,7 +3995,7 @@ pub const Object = struct { | ... | @@ -3995,7 +3995,7 @@ pub const Object = struct { |
| 3995 | } | 3995 | } |
| 3996 | const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size)); | 3996 | const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size)); |
| 3997 | const fields: [2]*llvm.Value = .{ | 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 | break :p o.context.constStruct(&fields, fields.len, .True); | 4000 | break :p o.context.constStruct(&fields, fields.len, .True); |
| 4001 | }; | 4001 | }; |
| ... | @@ -4020,7 +4020,7 @@ pub const Object = struct { | ... | @@ -4020,7 +4020,7 @@ pub const Object = struct { |
| 4020 | fields = .{ payload, llvm_tag_value, undefined }; | 4020 | fields = .{ payload, llvm_tag_value, undefined }; |
| 4021 | } | 4021 | } |
| 4022 | if (layout.padding != 0) { | 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 | fields_len = 3; | 4024 | fields_len = 3; |
| 4025 | } | 4025 | } |
| 4026 | if (need_unnamed) { | 4026 | if (need_unnamed) { |
| ... | @@ -4033,25 +4033,25 @@ pub const Object = struct { | ... | @@ -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 | const mod = o.module; | 4037 | const mod = o.module; |
| 4038 | switch (mod.intern_pool.indexToKey(val.toIntern())) { | 4038 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 4039 | .undef => return o.context.pointerType(0).getUndef(), | 4039 | .undef => return o.context.pointerType(0).getUndef(), |
| 4040 | .int => { | 4040 | .int => { |
| 4041 | var bigint_space: Value.BigIntSpace = undefined; | 4041 | var bigint_space: Value.BigIntSpace = undefined; |
| 4042 | const bigint = val.toBigInt(&bigint_space, mod); | 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 | return llvm_int.constIntToPtr(o.context.pointerType(0)); | 4044 | return llvm_int.constIntToPtr(o.context.pointerType(0)); |
| 4045 | }, | 4045 | }, |
| 4046 | else => unreachable, | 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 | const mod = o.module; | 4051 | const mod = o.module; |
| 4052 | const int_info = ty.intInfo(mod); | 4052 | const int_info = ty.intInfo(mod); |
| 4053 | assert(int_info.bits != 0); | 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 | const unsigned_val = v: { | 4056 | const unsigned_val = v: { |
| 4057 | if (bigint.limbs.len == 1) { | 4057 | if (bigint.limbs.len == 1) { |
| ... | @@ -4090,7 +4090,6 @@ pub const Object = struct { | ... | @@ -4090,7 +4090,6 @@ pub const Object = struct { |
| 4090 | | 4090 | |
| 4091 | fn lowerParentPtr(o: *Object, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { | 4091 | fn lowerParentPtr(o: *Object, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { |
| 4092 | const mod = o.module; | 4092 | const mod = o.module; |
| 4093 | const target = mod.getTarget(); | | |
| 4094 | return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { | 4093 | return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { |
| 4095 | .decl => |decl| o.lowerParentPtrDecl(ptr_val, decl), | 4094 | .decl => |decl| o.lowerParentPtrDecl(ptr_val, decl), |
| 4096 | .mut_decl => |mut_decl| o.lowerParentPtrDecl(ptr_val, mut_decl.decl), | 4095 | .mut_decl => |mut_decl| o.lowerParentPtrDecl(ptr_val, mut_decl.decl), |
| ... | @@ -4107,7 +4106,7 @@ pub const Object = struct { | ... | @@ -4107,7 +4106,7 @@ pub const Object = struct { |
| 4107 | } | 4106 | } |
| 4108 | | 4107 | |
| 4109 | const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; | 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 | const indices: [2]*llvm.Value = .{ | 4110 | const indices: [2]*llvm.Value = .{ |
| 4112 | llvm_u32.constInt(0, .False), | 4111 | llvm_u32.constInt(0, .False), |
| 4113 | llvm_u32.constInt(payload_offset, .False), | 4112 | llvm_u32.constInt(payload_offset, .False), |
| ... | @@ -4128,7 +4127,7 @@ pub const Object = struct { | ... | @@ -4128,7 +4127,7 @@ pub const Object = struct { |
| 4128 | return parent_llvm_ptr; | 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 | const indices: [2]*llvm.Value = .{ | 4131 | const indices: [2]*llvm.Value = .{ |
| 4133 | llvm_u32.constInt(0, .False), | 4132 | llvm_u32.constInt(0, .False), |
| 4134 | llvm_u32.constInt(0, .False), | 4133 | llvm_u32.constInt(0, .False), |
| ... | @@ -4153,7 +4152,7 @@ pub const Object = struct { | ... | @@ -4153,7 +4152,7 @@ pub const Object = struct { |
| 4153 | const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); | 4152 | const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); |
| 4154 | | 4153 | |
| 4155 | const field_index = @as(u32, @intCast(field_ptr.index)); | 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 | switch (parent_ty.zigTypeTag(mod)) { | 4156 | switch (parent_ty.zigTypeTag(mod)) { |
| 4158 | .Union => { | 4157 | .Union => { |
| 4159 | if (parent_ty.containerLayout(mod) == .Packed) { | 4158 | if (parent_ty.containerLayout(mod) == .Packed) { |
| ... | @@ -4180,7 +4179,7 @@ pub const Object = struct { | ... | @@ -4180,7 +4179,7 @@ pub const Object = struct { |
| 4180 | .Struct => { | 4179 | .Struct => { |
| 4181 | if (parent_ty.containerLayout(mod) == .Packed) { | 4180 | if (parent_ty.containerLayout(mod) == .Packed) { |
| 4182 | if (!byte_aligned) return parent_llvm_ptr; | 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 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); | 4183 | const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); |
| 4185 | // count bits of fields before this one | 4184 | // count bits of fields before this one |
| 4186 | const prev_bits = b: { | 4185 | const prev_bits = b: { |
| ... | @@ -4438,6 +4437,51 @@ pub const Object = struct { | ... | @@ -4438,6 +4437,51 @@ pub const Object = struct { |
| 4438 | llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty.toLlvm(&o.builder)); | 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 | pub const DeclGen = struct { | 4487 | pub const DeclGen = struct { |
| ... | @@ -4934,7 +4978,7 @@ pub const FuncGen = struct { | ... | @@ -4934,7 +4978,7 @@ pub const FuncGen = struct { |
| 4934 | | 4978 | |
| 4935 | const ret_ptr = if (!sret) null else blk: { | 4979 | const ret_ptr = if (!sret) null else blk: { |
| 4936 | const llvm_ret_ty = (try o.lowerType(return_type)).toLlvm(&o.builder); | 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 | try llvm_args.append(ret_ptr); | 4982 | try llvm_args.append(ret_ptr); |
| 4939 | break :blk ret_ptr; | 4983 | break :blk ret_ptr; |
| 4940 | }; | 4984 | }; |
| ... | @@ -4971,7 +5015,7 @@ pub const FuncGen = struct { | ... | @@ -4971,7 +5015,7 @@ pub const FuncGen = struct { |
| 4971 | } else { | 5015 | } else { |
| 4972 | const alignment = param_ty.abiAlignment(mod); | 5016 | const alignment = param_ty.abiAlignment(mod); |
| 4973 | const param_llvm_ty = llvm_arg.typeOf(); | 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 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); | 5019 | const store_inst = self.builder.buildStore(llvm_arg, arg_ptr); |
| 4976 | store_inst.setAlignment(alignment); | 5020 | store_inst.setAlignment(alignment); |
| 4977 | try llvm_args.append(arg_ptr); | 5021 | try llvm_args.append(arg_ptr); |
| ... | @@ -4984,7 +5028,7 @@ pub const FuncGen = struct { | ... | @@ -4984,7 +5028,7 @@ pub const FuncGen = struct { |
| 4984 | | 5028 | |
| 4985 | const alignment = param_ty.abiAlignment(mod); | 5029 | const alignment = param_ty.abiAlignment(mod); |
| 4986 | const param_llvm_ty = (try o.lowerType(param_ty)).toLlvm(&o.builder); | 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 | if (isByRef(param_ty, mod)) { | 5032 | if (isByRef(param_ty, mod)) { |
| 4989 | const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, ""); | 5033 | const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, ""); |
| 4990 | load_inst.setAlignment(alignment); | 5034 | load_inst.setAlignment(alignment); |
| ... | @@ -5003,7 +5047,7 @@ pub const FuncGen = struct { | ... | @@ -5003,7 +5047,7 @@ pub const FuncGen = struct { |
| 5003 | const param_ty = self.typeOf(arg); | 5047 | const param_ty = self.typeOf(arg); |
| 5004 | const llvm_arg = try self.resolveInst(arg); | 5048 | const llvm_arg = try self.resolveInst(arg); |
| 5005 | const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod))); | 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 | if (isByRef(param_ty, mod)) { | 5052 | if (isByRef(param_ty, mod)) { |
| 5009 | const alignment = param_ty.abiAlignment(mod); | 5053 | const alignment = param_ty.abiAlignment(mod); |
| ... | @@ -5017,7 +5061,7 @@ pub const FuncGen = struct { | ... | @@ -5017,7 +5061,7 @@ pub const FuncGen = struct { |
| 5017 | param_ty.abiAlignment(mod), | 5061 | param_ty.abiAlignment(mod), |
| 5018 | o.target_data.abiAlignmentOfType(int_llvm_ty), | 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 | const store_inst = self.builder.buildStore(llvm_arg, int_ptr); | 5065 | const store_inst = self.builder.buildStore(llvm_arg, int_ptr); |
| 5022 | store_inst.setAlignment(alignment); | 5066 | store_inst.setAlignment(alignment); |
| 5023 | const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); | 5067 | const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); |
| ... | @@ -5037,22 +5081,22 @@ pub const FuncGen = struct { | ... | @@ -5037,22 +5081,22 @@ pub const FuncGen = struct { |
| 5037 | .multiple_llvm_types => { | 5081 | .multiple_llvm_types => { |
| 5038 | const arg = args[it.zig_index - 1]; | 5082 | const arg = args[it.zig_index - 1]; |
| 5039 | const param_ty = self.typeOf(arg); | 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 | const llvm_arg = try self.resolveInst(arg); | 5085 | const llvm_arg = try self.resolveInst(arg); |
| 5042 | const is_by_ref = isByRef(param_ty, mod); | 5086 | const is_by_ref = isByRef(param_ty, mod); |
| 5043 | const arg_ptr = if (is_by_ref) llvm_arg else p: { | 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 | const store_inst = self.builder.buildStore(llvm_arg, p); | 5089 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 5046 | store_inst.setAlignment(param_ty.abiAlignment(mod)); | 5090 | store_inst.setAlignment(param_ty.abiAlignment(mod)); |
| 5047 | break :p p; | 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 | try llvm_args.ensureUnusedCapacity(it.types_len); | 5095 | try llvm_args.ensureUnusedCapacity(it.types_len); |
| 5052 | for (llvm_types, 0..) |field_ty, i_usize| { | 5096 | for (llvm_types, 0..) |field_ty, i_usize| { |
| 5053 | const i = @as(c_uint, @intCast(i_usize)); | 5097 | const i = @as(c_uint, @intCast(i_usize)); |
| 5054 | const field_ptr = self.builder.buildStructGEP(llvm_ty, arg_ptr, i, ""); | 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 | load_inst.setAlignment(target.ptrBitWidth() / 8); | 5100 | load_inst.setAlignment(target.ptrBitWidth() / 8); |
| 5057 | llvm_args.appendAssumeCapacity(load_inst); | 5101 | llvm_args.appendAssumeCapacity(load_inst); |
| 5058 | } | 5102 | } |
| ... | @@ -5060,7 +5104,7 @@ pub const FuncGen = struct { | ... | @@ -5060,7 +5104,7 @@ pub const FuncGen = struct { |
| 5060 | .as_u16 => { | 5104 | .as_u16 => { |
| 5061 | const arg = args[it.zig_index - 1]; | 5105 | const arg = args[it.zig_index - 1]; |
| 5062 | const llvm_arg = try self.resolveInst(arg); | 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 | try llvm_args.append(casted); | 5108 | try llvm_args.append(casted); |
| 5065 | }, | 5109 | }, |
| 5066 | .float_array => |count| { | 5110 | .float_array => |count| { |
| ... | @@ -5068,7 +5112,7 @@ pub const FuncGen = struct { | ... | @@ -5068,7 +5112,7 @@ pub const FuncGen = struct { |
| 5068 | const arg_ty = self.typeOf(arg); | 5112 | const arg_ty = self.typeOf(arg); |
| 5069 | var llvm_arg = try self.resolveInst(arg); | 5113 | var llvm_arg = try self.resolveInst(arg); |
| 5070 | if (!isByRef(arg_ty, mod)) { | 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 | const store_inst = self.builder.buildStore(llvm_arg, p); | 5116 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 5073 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); | 5117 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); |
| 5074 | llvm_arg = store_inst; | 5118 | llvm_arg = store_inst; |
| ... | @@ -5088,13 +5132,13 @@ pub const FuncGen = struct { | ... | @@ -5088,13 +5132,13 @@ pub const FuncGen = struct { |
| 5088 | const arg_ty = self.typeOf(arg); | 5132 | const arg_ty = self.typeOf(arg); |
| 5089 | var llvm_arg = try self.resolveInst(arg); | 5133 | var llvm_arg = try self.resolveInst(arg); |
| 5090 | if (!isByRef(arg_ty, mod)) { | 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 | const store_inst = self.builder.buildStore(llvm_arg, p); | 5136 | const store_inst = self.builder.buildStore(llvm_arg, p); |
| 5093 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); | 5137 | store_inst.setAlignment(arg_ty.abiAlignment(mod)); |
| 5094 | llvm_arg = store_inst; | 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 | const alignment = arg_ty.abiAlignment(mod); | 5142 | const alignment = arg_ty.abiAlignment(mod); |
| 5099 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); | 5143 | const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, ""); |
| 5100 | load_inst.setAlignment(alignment); | 5144 | load_inst.setAlignment(alignment); |
| ... | @@ -5198,7 +5242,7 @@ pub const FuncGen = struct { | ... | @@ -5198,7 +5242,7 @@ pub const FuncGen = struct { |
| 5198 | // a different LLVM type than the usual one. We solve this here at the callsite | 5242 | // a different LLVM type than the usual one. We solve this here at the callsite |
| 5199 | // by using our canonical type, then loading it if necessary. | 5243 | // by using our canonical type, then loading it if necessary. |
| 5200 | const alignment = o.target_data.abiAlignmentOfType(abi_ret_ty); | 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 | const store_inst = self.builder.buildStore(call, rp); | 5246 | const store_inst = self.builder.buildStore(call, rp); |
| 5203 | store_inst.setAlignment(alignment); | 5247 | store_inst.setAlignment(alignment); |
| 5204 | if (isByRef(return_type, mod)) { | 5248 | if (isByRef(return_type, mod)) { |
| ... | @@ -5214,7 +5258,7 @@ pub const FuncGen = struct { | ... | @@ -5214,7 +5258,7 @@ pub const FuncGen = struct { |
| 5214 | // our by-ref status disagrees with sret so we must allocate, store, | 5258 | // our by-ref status disagrees with sret so we must allocate, store, |
| 5215 | // and return the allocation pointer. | 5259 | // and return the allocation pointer. |
| 5216 | const alignment = return_type.abiAlignment(mod); | 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 | const store_inst = self.builder.buildStore(call, rp); | 5262 | const store_inst = self.builder.buildStore(call, rp); |
| 5219 | store_inst.setAlignment(alignment); | 5263 | store_inst.setAlignment(alignment); |
| 5220 | return rp; | 5264 | return rp; |
| ... | @@ -5235,7 +5279,7 @@ pub const FuncGen = struct { | ... | @@ -5235,7 +5279,7 @@ pub const FuncGen = struct { |
| 5235 | }); | 5279 | }); |
| 5236 | const null_opt_addr_global = try o.getNullOptAddr(); | 5280 | const null_opt_addr_global = try o.getNullOptAddr(); |
| 5237 | const target = mod.getTarget(); | 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 | // example: | 5283 | // example: |
| 5240 | // call fastcc void @test2.panic( | 5284 | // call fastcc void @test2.panic( |
| 5241 | // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr | 5285 | // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr |
| ... | @@ -5310,7 +5354,7 @@ pub const FuncGen = struct { | ... | @@ -5310,7 +5354,7 @@ pub const FuncGen = struct { |
| 5310 | return null; | 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 | const store_inst = self.builder.buildStore(operand, rp); | 5358 | const store_inst = self.builder.buildStore(operand, rp); |
| 5315 | store_inst.setAlignment(alignment); | 5359 | store_inst.setAlignment(alignment); |
| 5316 | const load_inst = self.builder.buildLoad(abi_ret_ty, rp, ""); | 5360 | const load_inst = self.builder.buildLoad(abi_ret_ty, rp, ""); |
| ... | @@ -5369,16 +5413,12 @@ pub const FuncGen = struct { | ... | @@ -5369,16 +5413,12 @@ pub const FuncGen = struct { |
| 5369 | const mod = o.module; | 5413 | const mod = o.module; |
| 5370 | | 5414 | |
| 5371 | const result_alignment = va_list_ty.abiAlignment(mod); | 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 | const llvm_fn_name = "llvm.va_copy"; | 5418 | const llvm_fn_name = "llvm.va_copy"; |
| 5375 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { | 5419 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 5376 | const param_types = [_]*llvm.Type{ | 5420 | const fn_type = try o.builder.fnType(.void, &.{ .ptr, .ptr }, .normal); |
| 5377 | self.context.pointerType(0), | 5421 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 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); | | |
| 5382 | }; | 5422 | }; |
| 5383 | | 5423 | |
| 5384 | const args: [2]*llvm.Value = .{ dest_list, src_list }; | 5424 | const args: [2]*llvm.Value = .{ dest_list, src_list }; |
| ... | @@ -5400,9 +5440,8 @@ pub const FuncGen = struct { | ... | @@ -5400,9 +5440,8 @@ pub const FuncGen = struct { |
| 5400 | | 5440 | |
| 5401 | const llvm_fn_name = "llvm.va_end"; | 5441 | const llvm_fn_name = "llvm.va_end"; |
| 5402 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { | 5442 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 5403 | const param_types = [_]*llvm.Type{self.context.pointerType(0)}; | 5443 | const fn_type = try o.builder.fnType(.void, &.{.ptr}, .normal); |
| 5404 | const fn_type = llvm.functionType(self.context.voidType(), &param_types, param_types.len, .False); | 5444 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 5405 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); | | |
| 5406 | }; | 5445 | }; |
| 5407 | const args: [1]*llvm.Value = .{list}; | 5446 | const args: [1]*llvm.Value = .{list}; |
| 5408 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 5447 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| ... | @@ -5416,13 +5455,12 @@ pub const FuncGen = struct { | ... | @@ -5416,13 +5455,12 @@ pub const FuncGen = struct { |
| 5416 | const llvm_va_list_ty = (try o.lowerType(va_list_ty)).toLlvm(&o.builder); | 5455 | const llvm_va_list_ty = (try o.lowerType(va_list_ty)).toLlvm(&o.builder); |
| 5417 | | 5456 | |
| 5418 | const result_alignment = va_list_ty.abiAlignment(mod); | 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 | const llvm_fn_name = "llvm.va_start"; | 5460 | const llvm_fn_name = "llvm.va_start"; |
| 5422 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { | 5461 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 5423 | const param_types = [_]*llvm.Type{self.context.pointerType(0)}; | 5462 | const fn_type = try o.builder.fnType(.void, &.{.ptr}, .normal); |
| 5424 | const fn_type = llvm.functionType(self.context.voidType(), &param_types, param_types.len, .False); | 5463 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 5425 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); | | |
| 5426 | }; | 5464 | }; |
| 5427 | const args: [1]*llvm.Value = .{list}; | 5465 | const args: [1]*llvm.Value = .{list}; |
| 5428 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 5466 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| ... | @@ -5495,7 +5533,7 @@ pub const FuncGen = struct { | ... | @@ -5495,7 +5533,7 @@ pub const FuncGen = struct { |
| 5495 | const opt_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); | 5533 | const opt_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); |
| 5496 | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); | 5534 | const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); |
| 5497 | const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); | 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 | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); | 5537 | const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); |
| 5500 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); | 5538 | const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); |
| 5501 | const lhs_shifted = self.builder.buildShl(lhs_non_null_i2, llvm_i2.constInt(1, .False), ""); | 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,7 +5567,7 @@ pub const FuncGen = struct { |
| 5529 | mixed_block, | 5567 | mixed_block, |
| 5530 | both_pl_block_end, | 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 | const llvm_i1_0 = llvm_i1.constInt(0, .False); | 5571 | const llvm_i1_0 = llvm_i1.constInt(0, .False); |
| 5534 | const llvm_i1_1 = llvm_i1.constInt(1, .False); | 5572 | const llvm_i1_1 = llvm_i1.constInt(1, .False); |
| 5535 | const incoming_values: [3]*llvm.Value = .{ | 5573 | const incoming_values: [3]*llvm.Value = .{ |
| ... | @@ -5767,13 +5805,11 @@ pub const FuncGen = struct { | ... | @@ -5767,13 +5805,11 @@ pub const FuncGen = struct { |
| 5767 | | 5805 | |
| 5768 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 5806 | fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 5769 | const o = self.dg.object; | 5807 | const o = self.dg.object; |
| 5770 | const mod = o.module; | | |
| 5771 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 5808 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 5772 | const cond = try self.resolveInst(pl_op.operand); | 5809 | const cond = try self.resolveInst(pl_op.operand); |
| 5773 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); | 5810 | const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); |
| 5774 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); | 5811 | const else_block = self.context.appendBasicBlock(self.llvm_func, "Else"); |
| 5775 | const target = mod.getTarget(); | 5812 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5776 | const llvm_usize = self.context.intType(target.ptrBitWidth()); | | |
| 5777 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) | 5813 | const cond_int = if (cond.typeOf().getTypeKind() == .Pointer) |
| 5778 | self.builder.buildPtrToInt(cond, llvm_usize, "") | 5814 | self.builder.buildPtrToInt(cond, llvm_usize, "") |
| 5779 | else | 5815 | else |
| ... | @@ -5874,48 +5910,46 @@ pub const FuncGen = struct { | ... | @@ -5874,48 +5910,46 @@ pub const FuncGen = struct { |
| 5874 | | 5910 | |
| 5875 | const dest_ty = self.typeOfIndex(inst); | 5911 | const dest_ty = self.typeOfIndex(inst); |
| 5876 | const dest_scalar_ty = dest_ty.scalarType(mod); | 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 | const target = mod.getTarget(); | 5914 | const target = mod.getTarget(); |
| 5879 | | 5915 | |
| 5880 | if (intrinsicsAllowed(dest_scalar_ty, target)) { | 5916 | if (intrinsicsAllowed(dest_scalar_ty, target)) { |
| 5881 | if (operand_scalar_ty.isSignedInt(mod)) { | 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 | } else { | 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 | const operand_bits = @as(u16, @intCast(operand_scalar_ty.bitSize(mod))); | 5924 | const operand_bits = @as(u16, @intCast(operand_scalar_ty.bitSize(mod))); |
| 5889 | const rt_int_bits = compilerRtIntBits(operand_bits); | 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 | var extended = e: { | 5927 | var extended = e: { |
| 5892 | if (operand_scalar_ty.isSignedInt(mod)) { | 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 | } else { | 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 | const dest_bits = dest_scalar_ty.floatBits(target); | 5934 | const dest_bits = dest_scalar_ty.floatBits(target); |
| 5899 | const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); | 5935 | const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5900 | const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); | 5936 | const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); |
| 5901 | const sign_prefix = if (operand_scalar_ty.isSignedInt(mod)) "" else "un"; | 5937 | const sign_prefix = if (operand_scalar_ty.isSignedInt(mod)) "" else "un"; |
| 5902 | var fn_name_buf: [64]u8 = undefined; | 5938 | const fn_name = try o.builder.fmt("__float{s}{s}i{s}f", .{ |
| 5903 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{ | | |
| 5904 | sign_prefix, | 5939 | sign_prefix, |
| 5905 | compiler_rt_operand_abbrev, | 5940 | compiler_rt_operand_abbrev, |
| 5906 | compiler_rt_dest_abbrev, | 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 | if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) { | 5945 | if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) { |
| 5911 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard | 5946 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard |
| 5912 | // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. | 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); | 5948 | param_type = try o.builder.vectorType(.normal, 2, .i64); |
| 5914 | extended = self.builder.buildBitCast(extended, v2i64, ""); | 5949 | extended = self.builder.buildBitCast(extended, param_type.toLlvm(&o.builder), ""); |
| 5915 | param_types = [1]*llvm.Type{v2i64}; | | |
| 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 | const params = [1]*llvm.Value{extended}; | 5953 | const params = [1]*llvm.Value{extended}; |
| 5920 | | 5954 | |
| 5921 | return self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, &params, params.len, .C, .Auto, ""); | 5955 | return self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, &params, params.len, .C, .Auto, ""); |
| ... | @@ -5935,23 +5969,23 @@ pub const FuncGen = struct { | ... | @@ -5935,23 +5969,23 @@ pub const FuncGen = struct { |
| 5935 | | 5969 | |
| 5936 | const dest_ty = self.typeOfIndex(inst); | 5970 | const dest_ty = self.typeOfIndex(inst); |
| 5937 | const dest_scalar_ty = dest_ty.scalarType(mod); | 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 | if (intrinsicsAllowed(operand_scalar_ty, target)) { | 5974 | if (intrinsicsAllowed(operand_scalar_ty, target)) { |
| 5941 | // TODO set fast math flag | 5975 | // TODO set fast math flag |
| 5942 | if (dest_scalar_ty.isSignedInt(mod)) { | 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 | } else { | 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)))); | 5983 | const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(mod))); |
| 5950 | const ret_ty = self.context.intType(rt_int_bits); | 5984 | const ret_ty = try o.builder.intType(rt_int_bits); |
| 5951 | const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { | 5985 | const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { |
| 5952 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard | 5986 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard |
| 5953 | // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. | 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 | } else ret_ty; | 5989 | } else ret_ty; |
| 5956 | | 5990 | |
| 5957 | const operand_bits = operand_scalar_ty.floatBits(target); | 5991 | const operand_bits = operand_scalar_ty.floatBits(target); |
| ... | @@ -5960,22 +5994,20 @@ pub const FuncGen = struct { | ... | @@ -5960,22 +5994,20 @@ pub const FuncGen = struct { |
| 5960 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); | 5994 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5961 | const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns"; | 5995 | const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns"; |
| 5962 | | 5996 | |
| 5963 | var fn_name_buf: [64]u8 = undefined; | 5997 | const fn_name = try o.builder.fmt("__fix{s}{s}f{s}i", .{ |
| 5964 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{ | | |
| 5965 | sign_prefix, | 5998 | sign_prefix, |
| 5966 | compiler_rt_operand_abbrev, | 5999 | compiler_rt_operand_abbrev, |
| 5967 | compiler_rt_dest_abbrev, | 6000 | compiler_rt_dest_abbrev, |
| 5968 | }) catch unreachable; | 6001 | }); |
| 5969 | | 6002 | |
| 5970 | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); | 6003 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 5971 | const param_types = [1]*llvm.Type{operand_llvm_ty}; | 6004 | const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); |
| 5972 | const libc_fn = try self.getLibcFunction(fn_name, &param_types, libc_ret_ty); | | |
| 5973 | const params = [1]*llvm.Value{operand}; | 6005 | const params = [1]*llvm.Value{operand}; |
| 5974 | | 6006 | |
| 5975 | var result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, &params, params.len, .C, .Auto, ""); | 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, ""); | 6009 | if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty.toLlvm(&o.builder), ""); |
| 5978 | if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); | 6010 | if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty.toLlvm(&o.builder), ""); |
| 5979 | return result; | 6011 | return result; |
| 5980 | } | 6012 | } |
| 5981 | | 6013 | |
| ... | @@ -5989,11 +6021,10 @@ pub const FuncGen = struct { | ... | @@ -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 | const o = fg.dg.object; | 6025 | const o = fg.dg.object; |
| 5994 | const mod = o.module; | 6026 | const mod = o.module; |
| 5995 | const target = mod.getTarget(); | 6027 | const llvm_usize_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 5996 | const llvm_usize_ty = fg.context.intType(target.ptrBitWidth()); | | |
| 5997 | switch (ty.ptrSize(mod)) { | 6028 | switch (ty.ptrSize(mod)) { |
| 5998 | .Slice => { | 6029 | .Slice => { |
| 5999 | const len = fg.builder.buildExtractValue(ptr, 1, ""); | 6030 | const len = fg.builder.buildExtractValue(ptr, 1, ""); |
| ... | @@ -6080,7 +6111,7 @@ pub const FuncGen = struct { | ... | @@ -6080,7 +6111,7 @@ pub const FuncGen = struct { |
| 6080 | const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder); | 6111 | const array_llvm_ty = (try o.lowerType(array_ty)).toLlvm(&o.builder); |
| 6081 | const elem_ty = array_ty.childType(mod); | 6112 | const elem_ty = array_ty.childType(mod); |
| 6082 | if (isByRef(array_ty, mod)) { | 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 | if (isByRef(elem_ty, mod)) { | 6115 | if (isByRef(elem_ty, mod)) { |
| 6085 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); | 6116 | const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); |
| 6086 | if (canElideLoad(self, body_tail)) | 6117 | if (canElideLoad(self, body_tail)) |
| ... | @@ -6128,7 +6159,7 @@ pub const FuncGen = struct { | ... | @@ -6128,7 +6159,7 @@ pub const FuncGen = struct { |
| 6128 | // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch | 6159 | // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch |
| 6129 | const ptr = if (ptr_ty.isSinglePointer(mod)) ptr: { | 6160 | const ptr = if (ptr_ty.isSinglePointer(mod)) ptr: { |
| 6130 | // If this is a single-item pointer to an array, we need another index in the GEP. | 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 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | 6163 | break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6133 | } else ptr: { | 6164 | } else ptr: { |
| 6134 | const indices: [1]*llvm.Value = .{rhs}; | 6165 | const indices: [1]*llvm.Value = .{rhs}; |
| ... | @@ -6162,7 +6193,7 @@ pub const FuncGen = struct { | ... | @@ -6162,7 +6193,7 @@ pub const FuncGen = struct { |
| 6162 | const llvm_elem_ty = (try o.lowerPtrElemTy(elem_ty)).toLlvm(&o.builder); | 6193 | const llvm_elem_ty = (try o.lowerPtrElemTy(elem_ty)).toLlvm(&o.builder); |
| 6163 | if (ptr_ty.isSinglePointer(mod)) { | 6194 | if (ptr_ty.isSinglePointer(mod)) { |
| 6164 | // If this is a single-item pointer to an array, we need another index in the GEP. | 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 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); | 6197 | return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); |
| 6167 | } else { | 6198 | } else { |
| 6168 | const indices: [1]*llvm.Value = .{rhs}; | 6199 | const indices: [1]*llvm.Value = .{rhs}; |
| ... | @@ -6216,12 +6247,12 @@ pub const FuncGen = struct { | ... | @@ -6216,12 +6247,12 @@ pub const FuncGen = struct { |
| 6216 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); | 6247 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); |
| 6217 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { | 6248 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6218 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); | 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 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 6251 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6221 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 6252 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6222 | } else if (field_ty.isPtrAtRuntime(mod)) { | 6253 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6223 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); | 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 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 6256 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 6226 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); | 6257 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 6227 | } | 6258 | } |
| ... | @@ -6238,12 +6269,12 @@ pub const FuncGen = struct { | ... | @@ -6238,12 +6269,12 @@ pub const FuncGen = struct { |
| 6238 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); | 6269 | const elem_llvm_ty = (try o.lowerType(field_ty)).toLlvm(&o.builder); |
| 6239 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { | 6270 | if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { |
| 6240 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); | 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 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); | 6273 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6243 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 6274 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 6244 | } else if (field_ty.isPtrAtRuntime(mod)) { | 6275 | } else if (field_ty.isPtrAtRuntime(mod)) { |
| 6245 | const elem_bits = @as(c_uint, @intCast(field_ty.bitSize(mod))); | 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 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); | 6278 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 6248 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); | 6279 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 6249 | } | 6280 | } |
| ... | @@ -6302,7 +6333,6 @@ pub const FuncGen = struct { | ... | @@ -6302,7 +6333,6 @@ pub const FuncGen = struct { |
| 6302 | | 6333 | |
| 6303 | const field_ptr = try self.resolveInst(extra.field_ptr); | 6334 | const field_ptr = try self.resolveInst(extra.field_ptr); |
| 6304 | | 6335 | |
| 6305 | const target = o.module.getTarget(); | | |
| 6306 | const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod); | 6336 | const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod); |
| 6307 | const field_offset = parent_ty.structFieldOffset(extra.field_index, mod); | 6337 | const field_offset = parent_ty.structFieldOffset(extra.field_index, mod); |
| 6308 | | 6338 | |
| ... | @@ -6310,7 +6340,7 @@ pub const FuncGen = struct { | ... | @@ -6310,7 +6340,7 @@ pub const FuncGen = struct { |
| 6310 | if (field_offset == 0) { | 6340 | if (field_offset == 0) { |
| 6311 | return field_ptr; | 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 | const field_ptr_int = self.builder.buildPtrToInt(field_ptr, llvm_usize_ty, ""); | 6345 | const field_ptr_int = self.builder.buildPtrToInt(field_ptr, llvm_usize_ty, ""); |
| 6316 | const base_ptr_int = self.builder.buildNUWSub(field_ptr_int, llvm_usize_ty.constInt(field_offset, .False), ""); | 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,7 +6523,7 @@ pub const FuncGen = struct { |
| 6493 | _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); | 6523 | _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); |
| 6494 | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { | 6524 | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 6495 | const alignment = operand_ty.abiAlignment(mod); | 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 | const store_inst = self.builder.buildStore(operand, alloca); | 6527 | const store_inst = self.builder.buildStore(operand, alloca); |
| 6498 | store_inst.setAlignment(alignment); | 6528 | store_inst.setAlignment(alignment); |
| 6499 | _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); | 6529 | _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); |
| ... | @@ -6532,7 +6562,7 @@ pub const FuncGen = struct { | ... | @@ -6532,7 +6562,7 @@ pub const FuncGen = struct { |
| 6532 | // The exact number of return / parameter values depends on which output values | 6562 | // The exact number of return / parameter values depends on which output values |
| 6533 | // are passed by reference as indirect outputs (determined below). | 6563 | // are passed by reference as indirect outputs (determined below). |
| 6534 | const max_return_count = outputs.len; | 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 | const llvm_ret_indirect = try arena.alloc(bool, max_return_count); | 6566 | const llvm_ret_indirect = try arena.alloc(bool, max_return_count); |
| 6537 | | 6567 | |
| 6538 | const max_param_count = inputs.len + outputs.len; | 6568 | const max_param_count = inputs.len + outputs.len; |
| ... | @@ -6571,7 +6601,7 @@ pub const FuncGen = struct { | ... | @@ -6571,7 +6601,7 @@ pub const FuncGen = struct { |
| 6571 | const output_inst = try self.resolveInst(output); | 6601 | const output_inst = try self.resolveInst(output); |
| 6572 | const output_ty = self.typeOf(output); | 6602 | const output_ty = self.typeOf(output); |
| 6573 | assert(output_ty.zigTypeTag(mod) == .Pointer); | 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 | if (llvm_ret_indirect[i]) { | 6606 | if (llvm_ret_indirect[i]) { |
| 6577 | // Pass the result by reference as an indirect output (e.g. "=*m") | 6607 | // Pass the result by reference as an indirect output (e.g. "=*m") |
| ... | @@ -6579,7 +6609,7 @@ pub const FuncGen = struct { | ... | @@ -6579,7 +6609,7 @@ pub const FuncGen = struct { |
| 6579 | | 6609 | |
| 6580 | llvm_param_values[llvm_param_i] = output_inst; | 6610 | llvm_param_values[llvm_param_i] = output_inst; |
| 6581 | llvm_param_types[llvm_param_i] = output_inst.typeOf(); | 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 | llvm_param_i += 1; | 6613 | llvm_param_i += 1; |
| 6584 | } else { | 6614 | } else { |
| 6585 | // Pass the result directly (e.g. "=r") | 6615 | // Pass the result directly (e.g. "=r") |
| ... | @@ -6588,7 +6618,7 @@ pub const FuncGen = struct { | ... | @@ -6588,7 +6618,7 @@ pub const FuncGen = struct { |
| 6588 | } | 6618 | } |
| 6589 | } else { | 6619 | } else { |
| 6590 | const ret_ty = self.typeOfIndex(inst); | 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 | llvm_ret_i += 1; | 6622 | llvm_ret_i += 1; |
| 6593 | } | 6623 | } |
| 6594 | | 6624 | |
| ... | @@ -6623,9 +6653,9 @@ pub const FuncGen = struct { | ... | @@ -6623,9 +6653,9 @@ pub const FuncGen = struct { |
| 6623 | | 6653 | |
| 6624 | const arg_llvm_value = try self.resolveInst(input); | 6654 | const arg_llvm_value = try self.resolveInst(input); |
| 6625 | const arg_ty = self.typeOf(input); | 6655 | const arg_ty = self.typeOf(input); |
| 6626 | var llvm_elem_ty: ?*llvm.Type = null; | 6656 | var llvm_elem_ty: Builder.Type = .none; |
| 6627 | if (isByRef(arg_ty, mod)) { | 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 | if (constraintAllowsMemory(constraint)) { | 6659 | if (constraintAllowsMemory(constraint)) { |
| 6630 | llvm_param_values[llvm_param_i] = arg_llvm_value; | 6660 | llvm_param_values[llvm_param_i] = arg_llvm_value; |
| 6631 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); | 6661 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| ... | @@ -6643,7 +6673,7 @@ pub const FuncGen = struct { | ... | @@ -6643,7 +6673,7 @@ pub const FuncGen = struct { |
| 6643 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); | 6673 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); |
| 6644 | } else { | 6674 | } else { |
| 6645 | const alignment = arg_ty.abiAlignment(mod); | 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 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); | 6677 | const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr); |
| 6648 | store_inst.setAlignment(alignment); | 6678 | store_inst.setAlignment(alignment); |
| 6649 | llvm_param_values[llvm_param_i] = arg_ptr; | 6679 | llvm_param_values[llvm_param_i] = arg_ptr; |
| ... | @@ -6671,8 +6701,10 @@ pub const FuncGen = struct { | ... | @@ -6671,8 +6701,10 @@ pub const FuncGen = struct { |
| 6671 | // In the case of indirect inputs, LLVM requires the callsite to have | 6701 | // In the case of indirect inputs, LLVM requires the callsite to have |
| 6672 | // an elementtype(<ty>) attribute. | 6702 | // an elementtype(<ty>) attribute. |
| 6673 | if (constraint[0] == '*') { | 6703 | if (constraint[0] == '*') { |
| 6674 | llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse | 6704 | llvm_param_attrs[llvm_param_i] = (if (llvm_elem_ty != .none) |
| 6675 | (try o.lowerPtrElemTy(arg_ty.childType(mod))).toLlvm(&o.builder); | 6705 | llvm_elem_ty |
| | 6706 | else |
| | 6707 | try o.lowerPtrElemTy(arg_ty.childType(mod))).toLlvm(&o.builder); |
| 6676 | } else { | 6708 | } else { |
| 6677 | llvm_param_attrs[llvm_param_i] = null; | 6709 | llvm_param_attrs[llvm_param_i] = null; |
| 6678 | } | 6710 | } |
| ... | @@ -6792,17 +6824,13 @@ pub const FuncGen = struct { | ... | @@ -6792,17 +6824,13 @@ pub const FuncGen = struct { |
| 6792 | } | 6824 | } |
| 6793 | | 6825 | |
| 6794 | const ret_llvm_ty = switch (return_count) { | 6826 | const ret_llvm_ty = switch (return_count) { |
| 6795 | 0 => self.context.voidType(), | 6827 | 0 => .void, |
| 6796 | 1 => llvm_ret_types[0], | 6828 | 1 => llvm_ret_types[0], |
| 6797 | else => self.context.structType( | 6829 | else => try o.builder.structType(.normal, llvm_ret_types), |
| 6798 | llvm_ret_types.ptr, | | |
| 6799 | @as(c_uint, @intCast(return_count)), | | |
| 6800 | .False, | | |
| 6801 | ), | | |
| 6802 | }; | 6830 | }; |
| 6803 | | 6831 | |
| 6804 | const llvm_fn_ty = llvm.functionType( | 6832 | const llvm_fn_ty = llvm.functionType( |
| 6805 | ret_llvm_ty, | 6833 | ret_llvm_ty.toLlvm(&o.builder), |
| 6806 | llvm_param_types.ptr, | 6834 | llvm_param_types.ptr, |
| 6807 | @as(c_uint, @intCast(param_count)), | 6835 | @as(c_uint, @intCast(param_count)), |
| 6808 | .False, | 6836 | .False, |
| ... | @@ -6891,7 +6919,7 @@ pub const FuncGen = struct { | ... | @@ -6891,7 +6919,7 @@ pub const FuncGen = struct { |
| 6891 | self.builder.buildLoad(optional_llvm_ty, operand, "") | 6919 | self.builder.buildLoad(optional_llvm_ty, operand, "") |
| 6892 | else | 6920 | else |
| 6893 | operand; | 6921 | operand; |
| 6894 | const llvm_i8 = self.context.intType(8); | 6922 | const llvm_i8 = Builder.Type.i8.toLlvm(&o.builder); |
| 6895 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); | 6923 | return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); |
| 6896 | } | 6924 | } |
| 6897 | | 6925 | |
| ... | @@ -6921,7 +6949,7 @@ pub const FuncGen = struct { | ... | @@ -6921,7 +6949,7 @@ pub const FuncGen = struct { |
| 6921 | const zero = err_set_ty.constNull(); | 6949 | const zero = err_set_ty.constNull(); |
| 6922 | | 6950 | |
| 6923 | if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { | 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 | switch (op) { | 6953 | switch (op) { |
| 6926 | .EQ => return llvm_i1.constInt(1, .False), // 0 == 0 | 6954 | .EQ => return llvm_i1.constInt(1, .False), // 0 == 0 |
| 6927 | .NE => return llvm_i1.constInt(0, .False), // 0 != 0 | 6955 | .NE => return llvm_i1.constInt(0, .False), // 0 != 0 |
| ... | @@ -6979,7 +7007,7 @@ pub const FuncGen = struct { | ... | @@ -6979,7 +7007,7 @@ pub const FuncGen = struct { |
| 6979 | const operand = try self.resolveInst(ty_op.operand); | 7007 | const operand = try self.resolveInst(ty_op.operand); |
| 6980 | const optional_ty = self.typeOf(ty_op.operand).childType(mod); | 7008 | const optional_ty = self.typeOf(ty_op.operand).childType(mod); |
| 6981 | const payload_ty = optional_ty.optionalChild(mod); | 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 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 7011 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 6984 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. | 7012 | // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. |
| 6985 | _ = self.builder.buildStore(non_null_bit, operand); | 7013 | _ = self.builder.buildStore(non_null_bit, operand); |
| ... | @@ -7165,7 +7193,7 @@ pub const FuncGen = struct { | ... | @@ -7165,7 +7193,7 @@ pub const FuncGen = struct { |
| 7165 | const mod = o.module; | 7193 | const mod = o.module; |
| 7166 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 7194 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 7167 | const payload_ty = self.typeOf(ty_op.operand); | 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 | comptime assert(optional_layout_version == 3); | 7197 | comptime assert(optional_layout_version == 3); |
| 7170 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit; | 7198 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit; |
| 7171 | const operand = try self.resolveInst(ty_op.operand); | 7199 | const operand = try self.resolveInst(ty_op.operand); |
| ... | @@ -7175,7 +7203,7 @@ pub const FuncGen = struct { | ... | @@ -7175,7 +7203,7 @@ pub const FuncGen = struct { |
| 7175 | } | 7203 | } |
| 7176 | const llvm_optional_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder); | 7204 | const llvm_optional_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder); |
| 7177 | if (isByRef(optional_ty, mod)) { | 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 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); | 7207 | const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); |
| 7180 | const payload_ptr_ty = try mod.singleMutPtrType(payload_ty); | 7208 | const payload_ptr_ty = try mod.singleMutPtrType(payload_ty); |
| 7181 | try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); | 7209 | try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); |
| ... | @@ -7203,7 +7231,7 @@ pub const FuncGen = struct { | ... | @@ -7203,7 +7231,7 @@ pub const FuncGen = struct { |
| 7203 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); | 7231 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 7204 | const error_offset = errUnionErrorOffset(payload_ty, mod); | 7232 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 7205 | if (isByRef(err_un_ty, mod)) { | 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 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); | 7235 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 7208 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); | 7236 | const store_inst = self.builder.buildStore(ok_err_code, err_ptr); |
| 7209 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); | 7237 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| ... | @@ -7232,7 +7260,7 @@ pub const FuncGen = struct { | ... | @@ -7232,7 +7260,7 @@ pub const FuncGen = struct { |
| 7232 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); | 7260 | const payload_offset = errUnionPayloadOffset(payload_ty, mod); |
| 7233 | const error_offset = errUnionErrorOffset(payload_ty, mod); | 7261 | const error_offset = errUnionErrorOffset(payload_ty, mod); |
| 7234 | if (isByRef(err_un_ty, mod)) { | 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 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); | 7264 | const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); |
| 7237 | const store_inst = self.builder.buildStore(operand, err_ptr); | 7265 | const store_inst = self.builder.buildStore(operand, err_ptr); |
| 7238 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); | 7266 | store_inst.setAlignment(Type.anyerror.abiAlignment(mod)); |
| ... | @@ -7252,8 +7280,8 @@ pub const FuncGen = struct { | ... | @@ -7252,8 +7280,8 @@ pub const FuncGen = struct { |
| 7252 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 7280 | fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 7253 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 7281 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7254 | const index = pl_op.payload; | 7282 | const index = pl_op.payload; |
| 7255 | const llvm_u32 = self.context.intType(32); | 7283 | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7256 | const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); | 7284 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32}); |
| 7257 | const args: [1]*llvm.Value = .{llvm_u32.constInt(index, .False)}; | 7285 | const args: [1]*llvm.Value = .{llvm_u32.constInt(index, .False)}; |
| 7258 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 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,8 +7290,8 @@ pub const FuncGen = struct { |
| 7262 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 7290 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 7263 | const index = pl_op.payload; | 7291 | const index = pl_op.payload; |
| 7264 | const operand = try self.resolveInst(pl_op.operand); | 7292 | const operand = try self.resolveInst(pl_op.operand); |
| 7265 | const llvm_u32 = self.context.intType(32); | 7293 | const llvm_u32 = Builder.Type.i32.toLlvm(&self.dg.object.builder); |
| 7266 | const llvm_fn = self.getIntrinsic("llvm.wasm.memory.grow", &.{llvm_u32}); | 7294 | const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32}); |
| 7267 | const args: [2]*llvm.Value = .{ | 7295 | const args: [2]*llvm.Value = .{ |
| 7268 | llvm_u32.constInt(index, .False), | 7296 | llvm_u32.constInt(index, .False), |
| 7269 | operand, | 7297 | operand, |
| ... | @@ -7371,8 +7399,7 @@ pub const FuncGen = struct { | ... | @@ -7371,8 +7399,7 @@ pub const FuncGen = struct { |
| 7371 | true => signed_intrinsic, | 7399 | true => signed_intrinsic, |
| 7372 | false => unsigned_intrinsic, | 7400 | false => unsigned_intrinsic, |
| 7373 | }; | 7401 | }; |
| 7374 | const llvm_inst_ty = (try o.lowerType(inst_ty)).toLlvm(&o.builder); | 7402 | const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{try o.lowerType(inst_ty)}); |
| 7375 | const llvm_fn = fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty}); | | |
| 7376 | const result_struct = fg.builder.buildCall( | 7403 | const result_struct = fg.builder.buildCall( |
| 7377 | llvm_fn.globalGetValueType(), | 7404 | llvm_fn.globalGetValueType(), |
| 7378 | llvm_fn, | 7405 | llvm_fn, |
| ... | @@ -7658,7 +7685,7 @@ pub const FuncGen = struct { | ... | @@ -7658,7 +7685,7 @@ pub const FuncGen = struct { |
| 7658 | switch (ptr_ty.ptrSize(mod)) { | 7685 | switch (ptr_ty.ptrSize(mod)) { |
| 7659 | .One => { | 7686 | .One => { |
| 7660 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | 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 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); | 7689 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); |
| 7663 | }, | 7690 | }, |
| 7664 | .C, .Many => { | 7691 | .C, .Many => { |
| ... | @@ -7687,7 +7714,7 @@ pub const FuncGen = struct { | ... | @@ -7687,7 +7714,7 @@ pub const FuncGen = struct { |
| 7687 | .One => { | 7714 | .One => { |
| 7688 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. | 7715 | // It's a pointer to an array, so according to LLVM we need an extra GEP index. |
| 7689 | const indices: [2]*llvm.Value = .{ | 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 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); | 7719 | return self.builder.buildInBoundsGEP(llvm_elem_ty, ptr, &indices, indices.len, ""); |
| 7693 | }, | 7720 | }, |
| ... | @@ -7723,10 +7750,9 @@ pub const FuncGen = struct { | ... | @@ -7723,10 +7750,9 @@ pub const FuncGen = struct { |
| 7723 | | 7750 | |
| 7724 | const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; | 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 | const llvm_dest_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); | 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 | const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); | 7756 | const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); |
| 7731 | | 7757 | |
| 7732 | const result = self.builder.buildExtractValue(result_struct, 0, ""); | 7758 | const result = self.builder.buildExtractValue(result_struct, 0, ""); |
| ... | @@ -7737,7 +7763,7 @@ pub const FuncGen = struct { | ... | @@ -7737,7 +7763,7 @@ pub const FuncGen = struct { |
| 7737 | | 7763 | |
| 7738 | if (isByRef(dest_ty, mod)) { | 7764 | if (isByRef(dest_ty, mod)) { |
| 7739 | const result_alignment = dest_ty.abiAlignment(mod); | 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 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); | 7768 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 7743 | const store_inst = self.builder.buildStore(result, field_ptr); | 7769 | const store_inst = self.builder.buildStore(result, field_ptr); |
| ... | @@ -7764,7 +7790,7 @@ pub const FuncGen = struct { | ... | @@ -7764,7 +7790,7 @@ pub const FuncGen = struct { |
| 7764 | vector_len: usize, | 7790 | vector_len: usize, |
| 7765 | ) !*llvm.Value { | 7791 | ) !*llvm.Value { |
| 7766 | const args_len = @as(c_uint, @intCast(args_vectors.len)); | 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 | assert(args_len <= 3); | 7794 | assert(args_len <= 3); |
| 7769 | | 7795 | |
| 7770 | var i: usize = 0; | 7796 | var i: usize = 0; |
| ... | @@ -7784,23 +7810,21 @@ pub const FuncGen = struct { | ... | @@ -7784,23 +7810,21 @@ pub const FuncGen = struct { |
| 7784 | | 7810 | |
| 7785 | fn getLibcFunction( | 7811 | fn getLibcFunction( |
| 7786 | self: *FuncGen, | 7812 | self: *FuncGen, |
| 7787 | fn_name: [:0]const u8, | 7813 | fn_name: Builder.String, |
| 7788 | param_types: []const *llvm.Type, | 7814 | param_types: []const Builder.Type, |
| 7789 | return_type: *llvm.Type, | 7815 | return_type: Builder.Type, |
| 7790 | ) Allocator.Error!*llvm.Value { | 7816 | ) Allocator.Error!*llvm.Value { |
| 7791 | const o = self.dg.object; | 7817 | const o = self.dg.object; |
| 7792 | return o.llvm_module.getNamedFunction(fn_name.ptr) orelse b: { | 7818 | const slice = fn_name.toSlice(&o.builder).?; |
| 7793 | const alias = o.llvm_module.getNamedGlobalAlias(fn_name.ptr, fn_name.len); | 7819 | return o.llvm_module.getNamedFunction(slice) orelse b: { |
| | 7820 | const alias = o.llvm_module.getNamedGlobalAlias(slice.ptr, slice.len); |
| 7794 | break :b if (alias) |a| a.getAliasee() else null; | 7821 | break :b if (alias) |a| a.getAliasee() else null; |
| 7795 | } orelse b: { | 7822 | } orelse b: { |
| 7796 | const name = try o.builder.string(fn_name); | 7823 | const fn_type = try o.builder.fnType(return_type, param_types, .normal); |
| 7797 | | 7824 | const f = o.llvm_module.addFunction(slice, fn_type.toLlvm(&o.builder)); |
| 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); | | |
| 7801 | | 7825 | |
| 7802 | var global = Builder.Global{ | 7826 | var global = Builder.Global{ |
| 7803 | .type = try o.builder.fnType(.void, &.{}, .normal), | 7827 | .type = fn_type, |
| 7804 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | 7828 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, |
| 7805 | }; | 7829 | }; |
| 7806 | var function = Builder.Function{ | 7830 | var function = Builder.Function{ |
| ... | @@ -7808,9 +7832,8 @@ pub const FuncGen = struct { | ... | @@ -7808,9 +7832,8 @@ pub const FuncGen = struct { |
| 7808 | }; | 7832 | }; |
| 7809 | | 7833 | |
| 7810 | try o.builder.llvm_globals.append(self.gpa, f); | 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 | try o.builder.functions.append(self.gpa, function); | 7836 | try o.builder.functions.append(self.gpa, function); |
| 7813 | | | |
| 7814 | break :b f; | 7837 | break :b f; |
| 7815 | }; | 7838 | }; |
| 7816 | } | 7839 | } |
| ... | @@ -7827,7 +7850,7 @@ pub const FuncGen = struct { | ... | @@ -7827,7 +7850,7 @@ pub const FuncGen = struct { |
| 7827 | const mod = o.module; | 7850 | const mod = o.module; |
| 7828 | const target = o.module.getTarget(); | 7851 | const target = o.module.getTarget(); |
| 7829 | const scalar_ty = ty.scalarType(mod); | 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 | if (intrinsicsAllowed(scalar_ty, target)) { | 7855 | if (intrinsicsAllowed(scalar_ty, target)) { |
| 7833 | const llvm_predicate: llvm.RealPredicate = switch (pred) { | 7856 | const llvm_predicate: llvm.RealPredicate = switch (pred) { |
| ... | @@ -7843,7 +7866,6 @@ pub const FuncGen = struct { | ... | @@ -7843,7 +7866,6 @@ pub const FuncGen = struct { |
| 7843 | | 7866 | |
| 7844 | const float_bits = scalar_ty.floatBits(target); | 7867 | const float_bits = scalar_ty.floatBits(target); |
| 7845 | const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits); | 7868 | const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits); |
| 7846 | var fn_name_buf: [64]u8 = undefined; | | |
| 7847 | const fn_base_name = switch (pred) { | 7869 | const fn_base_name = switch (pred) { |
| 7848 | .neq => "ne", | 7870 | .neq => "ne", |
| 7849 | .eq => "eq", | 7871 | .eq => "eq", |
| ... | @@ -7852,15 +7874,15 @@ pub const FuncGen = struct { | ... | @@ -7852,15 +7874,15 @@ pub const FuncGen = struct { |
| 7852 | .gt => "gt", | 7874 | .gt => "gt", |
| 7853 | .gte => "ge", | 7875 | .gte => "ge", |
| 7854 | }; | 7876 | }; |
| 7855 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f2", .{ | 7877 | const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); |
| 7856 | fn_base_name, compiler_rt_float_abbrev, | | |
| 7857 | }) catch unreachable; | | |
| 7858 | | 7878 | |
| 7859 | const param_types = [2]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty }; | 7879 | const libc_fn = try self.getLibcFunction( |
| 7860 | const llvm_i32 = self.context.intType(32); | 7880 | fn_name, |
| 7861 | const libc_fn = try self.getLibcFunction(fn_name, param_types[0..], llvm_i32); | 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 | const int_pred: llvm.IntPredicate = switch (pred) { | 7886 | const int_pred: llvm.IntPredicate = switch (pred) { |
| 7865 | .eq => .EQ, | 7887 | .eq => .EQ, |
| 7866 | .neq => .NE, | 7888 | .neq => .NE, |
| ... | @@ -7872,7 +7894,7 @@ pub const FuncGen = struct { | ... | @@ -7872,7 +7894,7 @@ pub const FuncGen = struct { |
| 7872 | | 7894 | |
| 7873 | if (ty.zigTypeTag(mod) == .Vector) { | 7895 | if (ty.zigTypeTag(mod) == .Vector) { |
| 7874 | const vec_len = ty.vectorLen(mod); | 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 | var result = vector_result_ty.getUndef(); | 7899 | var result = vector_result_ty.getUndef(); |
| 7878 | result = try self.buildElementwiseCall(libc_fn, &params, result, vec_len); | 7900 | result = try self.buildElementwiseCall(libc_fn, &params, result, vec_len); |
| ... | @@ -7913,7 +7935,7 @@ pub const FuncGen = struct { | ... | @@ -7913,7 +7935,7 @@ pub const FuncGen = struct { |
| 7913 | | 7935 | |
| 7914 | const FloatOpStrat = union(enum) { | 7936 | const FloatOpStrat = union(enum) { |
| 7915 | intrinsic: []const u8, | 7937 | intrinsic: []const u8, |
| 7916 | libc: [:0]const u8, | 7938 | libc: Builder.String, |
| 7917 | }; | 7939 | }; |
| 7918 | | 7940 | |
| 7919 | /// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.) | 7941 | /// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.) |
| ... | @@ -7930,11 +7952,10 @@ pub const FuncGen = struct { | ... | @@ -7930,11 +7952,10 @@ pub const FuncGen = struct { |
| 7930 | const mod = o.module; | 7952 | const mod = o.module; |
| 7931 | const target = mod.getTarget(); | 7953 | const target = mod.getTarget(); |
| 7932 | const scalar_ty = ty.scalarType(mod); | 7954 | const scalar_ty = ty.scalarType(mod); |
| 7933 | const llvm_ty = (try o.lowerType(ty)).toLlvm(&o.builder); | 7955 | const llvm_ty = try o.lowerType(ty); |
| 7934 | const scalar_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); | 7956 | const scalar_llvm_ty = try o.lowerType(scalar_ty); |
| 7935 | | 7957 | |
| 7936 | const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target); | 7958 | const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target); |
| 7937 | var fn_name_buf: [64]u8 = undefined; | | |
| 7938 | const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { | 7959 | const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) { |
| 7939 | // Some operations are dedicated LLVM instructions, not available as intrinsics | 7960 | // Some operations are dedicated LLVM instructions, not available as intrinsics |
| 7940 | .neg => return self.builder.buildFNeg(params[0], ""), | 7961 | .neg => return self.builder.buildFNeg(params[0], ""), |
| ... | @@ -7952,7 +7973,7 @@ pub const FuncGen = struct { | ... | @@ -7952,7 +7973,7 @@ pub const FuncGen = struct { |
| 7952 | .neg => { | 7973 | .neg => { |
| 7953 | // In this case we can generate a softfloat negation by XORing the | 7974 | // In this case we can generate a softfloat negation by XORing the |
| 7954 | // bits with a constant. | 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 | const one = int_llvm_ty.constInt(1, .False); | 7977 | const one = int_llvm_ty.constInt(1, .False); |
| 7957 | const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); | 7978 | const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False); |
| 7958 | const sign_mask = one.constShl(shift_amt); | 7979 | const sign_mask = one.constShl(shift_amt); |
| ... | @@ -7965,13 +7986,11 @@ pub const FuncGen = struct { | ... | @@ -7965,13 +7986,11 @@ pub const FuncGen = struct { |
| 7965 | const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, ""); | 7986 | const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, ""); |
| 7966 | break :blk self.builder.buildXor(bitcasted_operand, sign_mask, ""); | 7987 | break :blk self.builder.buildXor(bitcasted_operand, sign_mask, ""); |
| 7967 | }; | 7988 | }; |
| 7968 | return self.builder.buildBitCast(result, llvm_ty, ""); | 7989 | return self.builder.buildBitCast(result, llvm_ty.toLlvm(&o.builder), ""); |
| 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, | | |
| 7974 | }, | 7990 | }, |
| | 7991 | .add, .sub, .div, .mul => .{ .libc = try o.builder.fmt("__{s}{s}f3", .{ |
| | 7992 | @tagName(op), compilerRtFloatAbbrev(float_bits), |
| | 7993 | }) }, |
| 7975 | .ceil, | 7994 | .ceil, |
| 7976 | .cos, | 7995 | .cos, |
| 7977 | .exp, | 7996 | .exp, |
| ... | @@ -7990,21 +8009,22 @@ pub const FuncGen = struct { | ... | @@ -7990,21 +8009,22 @@ pub const FuncGen = struct { |
| 7990 | .sqrt, | 8009 | .sqrt, |
| 7991 | .tan, | 8010 | .tan, |
| 7992 | .trunc, | 8011 | .trunc, |
| 7993 | => FloatOpStrat{ | 8012 | => .{ .libc = try o.builder.fmt("{s}{s}{s}", .{ |
| 7994 | .libc = std.fmt.bufPrintZ(&fn_name_buf, "{s}{s}{s}", .{ | 8013 | libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), |
| 7995 | libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), | 8014 | }) }, |
| 7996 | }) catch unreachable, | | |
| 7997 | }, | | |
| 7998 | }; | 8015 | }; |
| 7999 | }; | 8016 | }; |
| 8000 | | 8017 | |
| 8001 | const llvm_fn: *llvm.Value = switch (strat) { | 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 | .libc => |fn_name| b: { | 8020 | .libc => |fn_name| b: { |
| 8004 | const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty }; | 8021 | const libc_fn = try self.getLibcFunction( |
| 8005 | const libc_fn = try self.getLibcFunction(fn_name, param_types[0..params.len], scalar_llvm_ty); | 8022 | fn_name, |
| | 8023 | ([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len], |
| | 8024 | scalar_llvm_ty, |
| | 8025 | ); |
| 8006 | if (ty.zigTypeTag(mod) == .Vector) { | 8026 | if (ty.zigTypeTag(mod) == .Vector) { |
| 8007 | const result = llvm_ty.getUndef(); | 8027 | const result = llvm_ty.toLlvm(&o.builder).getUndef(); |
| 8008 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod)); | 8028 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod)); |
| 8009 | } | 8029 | } |
| 8010 | | 8030 | |
| ... | @@ -8061,7 +8081,7 @@ pub const FuncGen = struct { | ... | @@ -8061,7 +8081,7 @@ pub const FuncGen = struct { |
| 8061 | | 8081 | |
| 8062 | if (isByRef(dest_ty, mod)) { | 8082 | if (isByRef(dest_ty, mod)) { |
| 8063 | const result_alignment = dest_ty.abiAlignment(mod); | 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 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); | 8086 | const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); |
| 8067 | const store_inst = self.builder.buildStore(result, field_ptr); | 8087 | const store_inst = self.builder.buildStore(result, field_ptr); |
| ... | @@ -8266,17 +8286,15 @@ pub const FuncGen = struct { | ... | @@ -8266,17 +8286,15 @@ pub const FuncGen = struct { |
| 8266 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); | 8286 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 8267 | return self.builder.buildFPTrunc(operand, dest_llvm_ty, ""); | 8287 | return self.builder.buildFPTrunc(operand, dest_llvm_ty, ""); |
| 8268 | } else { | 8288 | } else { |
| 8269 | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); | 8289 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 8270 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); | 8290 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 8271 | | 8291 | |
| 8272 | var fn_name_buf: [64]u8 = undefined; | 8292 | const fn_name = try o.builder.fmt("__trunc{s}f{s}f2", .{ |
| 8273 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__trunc{s}f{s}f2", .{ | | |
| 8274 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | 8293 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 8275 | }) catch unreachable; | 8294 | }); |
| 8276 | | 8295 | |
| 8277 | const params = [1]*llvm.Value{operand}; | 8296 | const params = [1]*llvm.Value{operand}; |
| 8278 | const param_types = [1]*llvm.Type{operand_llvm_ty}; | 8297 | const llvm_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); |
| 8279 | const llvm_fn = try self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); | | |
| 8280 | | 8298 | |
| 8281 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .C, .Auto, ""); | 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,17 +8315,15 @@ pub const FuncGen = struct { |
| 8297 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); | 8315 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); |
| 8298 | return self.builder.buildFPExt(operand, dest_llvm_ty, ""); | 8316 | return self.builder.buildFPExt(operand, dest_llvm_ty, ""); |
| 8299 | } else { | 8317 | } else { |
| 8300 | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); | 8318 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 8301 | const dest_llvm_ty = (try o.lowerType(dest_ty)).toLlvm(&o.builder); | 8319 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 8302 | | 8320 | |
| 8303 | var fn_name_buf: [64]u8 = undefined; | 8321 | const fn_name = try o.builder.fmt("__extend{s}f{s}f2", .{ |
| 8304 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__extend{s}f{s}f2", .{ | | |
| 8305 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | 8322 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 8306 | }) catch unreachable; | 8323 | }); |
| 8307 | | 8324 | |
| 8308 | const params = [1]*llvm.Value{operand}; | 8325 | const params = [1]*llvm.Value{operand}; |
| 8309 | const param_types = [1]*llvm.Type{operand_llvm_ty}; | 8326 | const llvm_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); |
| 8310 | const llvm_fn = try self.getLibcFunction(fn_name, &param_types, dest_llvm_ty); | | |
| 8311 | | 8327 | |
| 8312 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .C, .Auto, ""); | 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,7 +8374,7 @@ pub const FuncGen = struct { |
| 8358 | if (!result_is_ref) { | 8374 | if (!result_is_ref) { |
| 8359 | return self.dg.todo("implement bitcast vector to non-ref array", .{}); | 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 | const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8; | 8378 | const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8; |
| 8363 | if (bitcast_ok) { | 8379 | if (bitcast_ok) { |
| 8364 | const llvm_store = self.builder.buildStore(operand, array_ptr); | 8380 | const llvm_store = self.builder.buildStore(operand, array_ptr); |
| ... | @@ -8367,7 +8383,7 @@ pub const FuncGen = struct { | ... | @@ -8367,7 +8383,7 @@ pub const FuncGen = struct { |
| 8367 | // If the ABI size of the element type is not evenly divisible by size in bits; | 8383 | // If the ABI size of the element type is not evenly divisible by size in bits; |
| 8368 | // a simple bitcast will not work, and we fall back to extractelement. | 8384 | // a simple bitcast will not work, and we fall back to extractelement. |
| 8369 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); | 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 | const zero = llvm_usize.constNull(); | 8387 | const zero = llvm_usize.constNull(); |
| 8372 | const vector_len = operand_ty.arrayLen(mod); | 8388 | const vector_len = operand_ty.arrayLen(mod); |
| 8373 | var i: u64 = 0; | 8389 | var i: u64 = 0; |
| ... | @@ -8401,7 +8417,7 @@ pub const FuncGen = struct { | ... | @@ -8401,7 +8417,7 @@ pub const FuncGen = struct { |
| 8401 | const array_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); | 8417 | const array_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); |
| 8402 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); | 8418 | const elem_llvm_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 8403 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); | 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 | const zero = llvm_usize.constNull(); | 8421 | const zero = llvm_usize.constNull(); |
| 8406 | const vector_len = operand_ty.arrayLen(mod); | 8422 | const vector_len = operand_ty.arrayLen(mod); |
| 8407 | var vector = llvm_vector_ty.getUndef(); | 8423 | var vector = llvm_vector_ty.getUndef(); |
| ... | @@ -8427,7 +8443,7 @@ pub const FuncGen = struct { | ... | @@ -8427,7 +8443,7 @@ pub const FuncGen = struct { |
| 8427 | | 8443 | |
| 8428 | if (result_is_ref) { | 8444 | if (result_is_ref) { |
| 8429 | const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod)); | 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 | const store_inst = self.builder.buildStore(operand, result_ptr); | 8447 | const store_inst = self.builder.buildStore(operand, result_ptr); |
| 8432 | store_inst.setAlignment(alignment); | 8448 | store_inst.setAlignment(alignment); |
| 8433 | return result_ptr; | 8449 | return result_ptr; |
| ... | @@ -8438,7 +8454,7 @@ pub const FuncGen = struct { | ... | @@ -8438,7 +8454,7 @@ pub const FuncGen = struct { |
| 8438 | // but LLVM won't let us bitcast struct values. | 8454 | // but LLVM won't let us bitcast struct values. |
| 8439 | // Therefore, we store operand to alloca, then load for result. | 8455 | // Therefore, we store operand to alloca, then load for result. |
| 8440 | const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod)); | 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 | const store_inst = self.builder.buildStore(operand, result_ptr); | 8458 | const store_inst = self.builder.buildStore(operand, result_ptr); |
| 8443 | store_inst.setAlignment(alignment); | 8459 | store_inst.setAlignment(alignment); |
| 8444 | const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); | 8460 | const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); |
| ... | @@ -8489,7 +8505,7 @@ pub const FuncGen = struct { | ... | @@ -8489,7 +8505,7 @@ pub const FuncGen = struct { |
| 8489 | _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); | 8505 | _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); |
| 8490 | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { | 8506 | } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { |
| 8491 | const alignment = inst_ty.abiAlignment(mod); | 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 | const store_inst = self.builder.buildStore(arg_val, alloca); | 8509 | const store_inst = self.builder.buildStore(arg_val, alloca); |
| 8494 | store_inst.setAlignment(alignment); | 8510 | store_inst.setAlignment(alignment); |
| 8495 | _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); | 8511 | _ = dib.insertDeclareAtEnd(alloca, di_local_var, debug_loc, insert_block); |
| ... | @@ -8527,11 +8543,11 @@ pub const FuncGen = struct { | ... | @@ -8527,11 +8543,11 @@ pub const FuncGen = struct { |
| 8527 | | 8543 | |
| 8528 | /// Use this instead of builder.buildAlloca, because this function makes sure to | 8544 | /// Use this instead of builder.buildAlloca, because this function makes sure to |
| 8529 | /// put the alloca instruction at the top of the function! | 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 | const o = self.dg.object; | 8547 | const o = self.dg.object; |
| 8532 | const mod = o.module; | 8548 | const mod = o.module; |
| 8533 | const target = mod.getTarget(); | 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 | fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { | 8553 | fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { |
| ... | @@ -8547,7 +8563,7 @@ pub const FuncGen = struct { | ... | @@ -8547,7 +8563,7 @@ pub const FuncGen = struct { |
| 8547 | // Even if safety is disabled, we still emit a memset to undefined since it conveys | 8563 | // Even if safety is disabled, we still emit a memset to undefined since it conveys |
| 8548 | // extra information to LLVM. However, safety makes the difference between using | 8564 | // extra information to LLVM. However, safety makes the difference between using |
| 8549 | // 0xaa or actual undefined for the fill byte. | 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 | const fill_byte = if (safety) | 8567 | const fill_byte = if (safety) |
| 8552 | u8_llvm_ty.constInt(0xaa, .False) | 8568 | u8_llvm_ty.constInt(0xaa, .False) |
| 8553 | else | 8569 | else |
| ... | @@ -8558,7 +8574,7 @@ pub const FuncGen = struct { | ... | @@ -8558,7 +8574,7 @@ pub const FuncGen = struct { |
| 8558 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); | 8574 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); |
| 8559 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod)); | 8575 | _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod)); |
| 8560 | if (safety and mod.comp.bin_file.options.valgrind) { | 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 | return null; | 8579 | return null; |
| 8564 | } | 8580 | } |
| ... | @@ -8609,7 +8625,7 @@ pub const FuncGen = struct { | ... | @@ -8609,7 +8625,7 @@ pub const FuncGen = struct { |
| 8609 | | 8625 | |
| 8610 | fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8626 | fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8611 | _ = inst; | 8627 | _ = inst; |
| 8612 | const llvm_fn = self.getIntrinsic("llvm.trap", &.{}); | 8628 | const llvm_fn = try self.getIntrinsic("llvm.trap", &.{}); |
| 8613 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .Cold, .Auto, ""); | 8629 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .Cold, .Auto, ""); |
| 8614 | _ = self.builder.buildUnreachable(); | 8630 | _ = self.builder.buildUnreachable(); |
| 8615 | return null; | 8631 | return null; |
| ... | @@ -8617,7 +8633,7 @@ pub const FuncGen = struct { | ... | @@ -8617,7 +8633,7 @@ pub const FuncGen = struct { |
| 8617 | | 8633 | |
| 8618 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8634 | fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8619 | _ = inst; | 8635 | _ = inst; |
| 8620 | const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); | 8636 | const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{}); |
| 8621 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .C, .Auto, ""); | 8637 | _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .C, .Auto, ""); |
| 8622 | return null; | 8638 | return null; |
| 8623 | } | 8639 | } |
| ... | @@ -8633,8 +8649,8 @@ pub const FuncGen = struct { | ... | @@ -8633,8 +8649,8 @@ pub const FuncGen = struct { |
| 8633 | return llvm_usize.constNull(); | 8649 | return llvm_usize.constNull(); |
| 8634 | } | 8650 | } |
| 8635 | | 8651 | |
| 8636 | const llvm_i32 = self.context.intType(32); | 8652 | const llvm_i32 = Builder.Type.i32.toLlvm(&o.builder); |
| 8637 | const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); | 8653 | const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{}); |
| 8638 | const params = [_]*llvm.Value{llvm_i32.constNull()}; | 8654 | const params = [_]*llvm.Value{llvm_i32.constNull()}; |
| 8639 | const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, ""); | 8655 | const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 8640 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); | 8656 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); |
| ... | @@ -8643,16 +8659,13 @@ pub const FuncGen = struct { | ... | @@ -8643,16 +8659,13 @@ pub const FuncGen = struct { |
| 8643 | fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { | 8659 | fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { |
| 8644 | _ = inst; | 8660 | _ = inst; |
| 8645 | const o = self.dg.object; | 8661 | const o = self.dg.object; |
| 8646 | const llvm_i32 = self.context.intType(32); | | |
| 8647 | const llvm_fn_name = "llvm.frameaddress.p0"; | 8662 | const llvm_fn_name = "llvm.frameaddress.p0"; |
| 8648 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { | 8663 | const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 8649 | const llvm_p0i8 = self.context.pointerType(0); | 8664 | const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal); |
| 8650 | const param_types = [_]*llvm.Type{llvm_i32}; | 8665 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 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); | | |
| 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 | const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, ""); | 8669 | const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &params, params.len, .Fast, .Auto, ""); |
| 8657 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); | 8670 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 8658 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); | 8671 | return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); |
| ... | @@ -8841,9 +8854,8 @@ pub const FuncGen = struct { | ... | @@ -8841,9 +8854,8 @@ pub const FuncGen = struct { |
| 8841 | const dest_slice = try self.resolveInst(bin_op.lhs); | 8854 | const dest_slice = try self.resolveInst(bin_op.lhs); |
| 8842 | const ptr_ty = self.typeOf(bin_op.lhs); | 8855 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 8843 | const elem_ty = self.typeOf(bin_op.rhs); | 8856 | const elem_ty = self.typeOf(bin_op.rhs); |
| 8844 | const target = mod.getTarget(); | | |
| 8845 | const dest_ptr_align = ptr_ty.ptrAlignment(mod); | 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 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty); | 8859 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty); |
| 8848 | const is_volatile = ptr_ty.isVolatilePtr(mod); | 8860 | const is_volatile = ptr_ty.isVolatilePtr(mod); |
| 8849 | | 8861 | |
| ... | @@ -8864,7 +8876,7 @@ pub const FuncGen = struct { | ... | @@ -8864,7 +8876,7 @@ pub const FuncGen = struct { |
| 8864 | u8_llvm_ty.constInt(0xaa, .False) | 8876 | u8_llvm_ty.constInt(0xaa, .False) |
| 8865 | else | 8877 | else |
| 8866 | u8_llvm_ty.getUndef(); | 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 | if (intrinsic_len0_traps) { | 8880 | if (intrinsic_len0_traps) { |
| 8869 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8881 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| 8870 | } else { | 8882 | } else { |
| ... | @@ -8872,7 +8884,7 @@ pub const FuncGen = struct { | ... | @@ -8872,7 +8884,7 @@ pub const FuncGen = struct { |
| 8872 | } | 8884 | } |
| 8873 | | 8885 | |
| 8874 | if (safety and mod.comp.bin_file.options.valgrind) { | 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 | return null; | 8889 | return null; |
| 8878 | } | 8890 | } |
| ... | @@ -8886,7 +8898,7 @@ pub const FuncGen = struct { | ... | @@ -8886,7 +8898,7 @@ pub const FuncGen = struct { |
| 8886 | .ty = Type.u8, | 8898 | .ty = Type.u8, |
| 8887 | .val = byte_val, | 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 | if (intrinsic_len0_traps) { | 8903 | if (intrinsic_len0_traps) { |
| 8892 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8904 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | @@ -8903,7 +8915,7 @@ pub const FuncGen = struct { | ... | @@ -8903,7 +8915,7 @@ pub const FuncGen = struct { |
| 8903 | if (elem_abi_size == 1) { | 8915 | if (elem_abi_size == 1) { |
| 8904 | // In this case we can take advantage of LLVM's intrinsic. | 8916 | // In this case we can take advantage of LLVM's intrinsic. |
| 8905 | const fill_byte = try self.bitCast(value, elem_ty, Type.u8); | 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 | if (intrinsic_len0_traps) { | 8920 | if (intrinsic_len0_traps) { |
| 8909 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); | 8921 | try self.safeWasmMemset(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile); |
| ... | @@ -8934,7 +8946,7 @@ pub const FuncGen = struct { | ... | @@ -8934,7 +8946,7 @@ pub const FuncGen = struct { |
| 8934 | const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody"); | 8946 | const body_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetBody"); |
| 8935 | const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd"); | 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 | const len = switch (ptr_ty.ptrSize(mod)) { | 8950 | const len = switch (ptr_ty.ptrSize(mod)) { |
| 8939 | .Slice => self.builder.buildExtractValue(dest_slice, 1, ""), | 8951 | .Slice => self.builder.buildExtractValue(dest_slice, 1, ""), |
| 8940 | .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False), | 8952 | .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False), |
| ... | @@ -9008,7 +9020,7 @@ pub const FuncGen = struct { | ... | @@ -9008,7 +9020,7 @@ pub const FuncGen = struct { |
| 9008 | const src_slice = try self.resolveInst(bin_op.rhs); | 9020 | const src_slice = try self.resolveInst(bin_op.rhs); |
| 9009 | const src_ptr_ty = self.typeOf(bin_op.rhs); | 9021 | const src_ptr_ty = self.typeOf(bin_op.rhs); |
| 9010 | const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty); | 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 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); | 9024 | const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); |
| 9013 | const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod); | 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,9 +9135,8 @@ pub const FuncGen = struct { |
| 9123 | const operand_ty = self.typeOf(ty_op.operand); | 9135 | const operand_ty = self.typeOf(ty_op.operand); |
| 9124 | const operand = try self.resolveInst(ty_op.operand); | 9136 | const operand = try self.resolveInst(ty_op.operand); |
| 9125 | | 9137 | |
| 9126 | const llvm_i1 = self.context.intType(1); | 9138 | const llvm_i1 = Builder.Type.i1.toLlvm(&o.builder); |
| 9127 | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); | 9139 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{try o.lowerType(operand_ty)}); |
| 9128 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); | | |
| 9129 | | 9140 | |
| 9130 | const params = [_]*llvm.Value{ operand, llvm_i1.constNull() }; | 9141 | const params = [_]*llvm.Value{ operand, llvm_i1.constNull() }; |
| 9131 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); | 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,8 +9162,7 @@ pub const FuncGen = struct { |
| 9151 | const operand = try self.resolveInst(ty_op.operand); | 9162 | const operand = try self.resolveInst(ty_op.operand); |
| 9152 | | 9163 | |
| 9153 | const params = [_]*llvm.Value{operand}; | 9164 | const params = [_]*llvm.Value{operand}; |
| 9154 | const operand_llvm_ty = (try o.lowerType(operand_ty)).toLlvm(&o.builder); | 9165 | const fn_val = try self.getIntrinsic(llvm_fn_name, &.{try o.lowerType(operand_ty)}); |
| 9155 | const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); | | |
| 9156 | | 9166 | |
| 9157 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); | 9167 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); |
| 9158 | const result_ty = self.typeOfIndex(inst); | 9168 | const result_ty = self.typeOfIndex(inst); |
| ... | @@ -9178,15 +9188,16 @@ pub const FuncGen = struct { | ... | @@ -9178,15 +9188,16 @@ pub const FuncGen = struct { |
| 9178 | assert(bits % 8 == 0); | 9188 | assert(bits % 8 == 0); |
| 9179 | | 9189 | |
| 9180 | var operand = try self.resolveInst(ty_op.operand); | 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 | if (bits % 16 == 8) { | 9193 | if (bits % 16 == 8) { |
| 9184 | // If not an even byte-multiple, we need zero-extend + shift-left 1 byte | 9194 | // If not an even byte-multiple, we need zero-extend + shift-left 1 byte |
| 9185 | // The truncated result at the end will be the correct bswap | 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 | if (operand_ty.zigTypeTag(mod) == .Vector) { | 9198 | if (operand_ty.zigTypeTag(mod) == .Vector) { |
| 9188 | const vec_len = operand_ty.vectorLen(mod); | 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 | const shifts = try self.gpa.alloc(*llvm.Value, vec_len); | 9202 | const shifts = try self.gpa.alloc(*llvm.Value, vec_len); |
| 9192 | defer self.gpa.free(shifts); | 9203 | defer self.gpa.free(shifts); |
| ... | @@ -9196,18 +9207,18 @@ pub const FuncGen = struct { | ... | @@ -9196,18 +9207,18 @@ pub const FuncGen = struct { |
| 9196 | } | 9207 | } |
| 9197 | const shift_vec = llvm.constVector(shifts.ptr, vec_len); | 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 | operand = self.builder.buildShl(extended, shift_vec, ""); | 9211 | operand = self.builder.buildShl(extended, shift_vec, ""); |
| 9201 | } else { | 9212 | } else { |
| 9202 | const extended = self.builder.buildZExt(operand, scalar_llvm_ty, ""); | 9213 | const extended = self.builder.buildZExt(operand, scalar_llvm_ty, ""); |
| 9203 | operand = self.builder.buildShl(extended, scalar_llvm_ty.constInt(8, .False), ""); | 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 | bits = bits + 8; | 9217 | bits = bits + 8; |
| 9207 | } | 9218 | } |
| 9208 | | 9219 | |
| 9209 | const params = [_]*llvm.Value{operand}; | 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 | const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, ""); | 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,7 +9263,7 @@ pub const FuncGen = struct { |
| 9252 | | 9263 | |
| 9253 | self.builder.positionBuilderAtEnd(end_block); | 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 | const incoming_values: [2]*llvm.Value = .{ | 9267 | const incoming_values: [2]*llvm.Value = .{ |
| 9257 | llvm_type.constInt(1, .False), llvm_type.constInt(0, .False), | 9268 | llvm_type.constInt(1, .False), llvm_type.constInt(0, .False), |
| 9258 | }; | 9269 | }; |
| ... | @@ -9281,25 +9292,30 @@ pub const FuncGen = struct { | ... | @@ -9281,25 +9292,30 @@ pub const FuncGen = struct { |
| 9281 | | 9292 | |
| 9282 | // TODO: detect when the type changes and re-emit this function. | 9293 | // TODO: detect when the type changes and re-emit this function. |
| 9283 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); | 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 | errdefer assert(o.named_enum_map.remove(enum_type.decl)); | 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 | const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); | 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)}); | 9299 | const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{ |
| 9293 | | 9300 | fqn.fmt(&mod.intern_pool), |
| 9294 | const param_types = [_]*llvm.Type{(try o.lowerType(enum_type.tag_ty.toType())).toLlvm(&o.builder)}; | 9301 | }); |
| 9295 | | 9302 | |
| 9296 | const llvm_ret_ty = (try o.lowerType(Type.bool)).toLlvm(&o.builder); | 9303 | const fn_type = try o.builder.fnType(.i1, &.{try o.lowerType( |
| 9297 | const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False); | 9304 | enum_type.tag_ty.toType(), |
| 9298 | const fn_val = o.llvm_module.addFunction(llvm_fn_name, fn_type); | 9305 | )}, .normal); |
| | 9306 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9299 | fn_val.setLinkage(.Internal); | 9307 | fn_val.setLinkage(.Internal); |
| 9300 | fn_val.setFunctionCallConv(.Fast); | 9308 | fn_val.setFunctionCallConv(.Fast); |
| 9301 | o.addCommonFnAttributes(fn_val); | 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 | const prev_block = self.builder.getInsertBlock(); | 9320 | const prev_block = self.builder.getInsertBlock(); |
| 9305 | const prev_debug_location = self.builder.getCurrentDebugLocation2(); | 9321 | const prev_debug_location = self.builder.getCurrentDebugLocation2(); |
| ... | @@ -9330,10 +9346,15 @@ pub const FuncGen = struct { | ... | @@ -9330,10 +9346,15 @@ pub const FuncGen = struct { |
| 9330 | switch_instr.addCase(this_tag_int_value, named_block); | 9346 | switch_instr.addCase(this_tag_int_value, named_block); |
| 9331 | } | 9347 | } |
| 9332 | self.builder.positionBuilderAtEnd(named_block); | 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 | self.builder.positionBuilderAtEnd(unnamed_block); | 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 | return fn_val; | 9358 | return fn_val; |
| 9338 | } | 9359 | } |
| 9339 | | 9360 | |
| ... | @@ -9361,20 +9382,22 @@ pub const FuncGen = struct { | ... | @@ -9361,20 +9382,22 @@ pub const FuncGen = struct { |
| 9361 | const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); | 9382 | const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); |
| 9362 | | 9383 | |
| 9363 | const slice_ty = Type.slice_const_u8_sentinel_0; | 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 | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); | 9387 | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 9366 | const slice_alignment = slice_ty.abiAlignment(mod); | 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)}; | 9390 | const fn_type = try o.builder.fnType(ret_ty, &.{ |
| 9369 | | 9391 | try o.lowerType(enum_type.tag_ty.toType()), |
| 9370 | const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False); | 9392 | }, .normal); |
| 9371 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type); | 9393 | const fn_val = o.llvm_module.addFunction(llvm_fn_name.toSlice(&o.builder).?, fn_type.toLlvm(&o.builder)); |
| 9372 | fn_val.setLinkage(.Internal); | 9394 | fn_val.setLinkage(.Internal); |
| 9373 | fn_val.setFunctionCallConv(.Fast); | 9395 | fn_val.setFunctionCallConv(.Fast); |
| 9374 | o.addCommonFnAttributes(fn_val); | 9396 | o.addCommonFnAttributes(fn_val); |
| 9375 | | 9397 | |
| 9376 | var global = Builder.Global{ | 9398 | var global = Builder.Global{ |
| 9377 | .type = try o.builder.fnType(.void, &.{}, .normal), | 9399 | .linkage = .internal, |
| | 9400 | .type = fn_type, |
| 9378 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, | 9401 | .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, |
| 9379 | }; | 9402 | }; |
| 9380 | var function = Builder.Function{ | 9403 | var function = Builder.Function{ |
| ... | @@ -9457,15 +9480,24 @@ pub const FuncGen = struct { | ... | @@ -9457,15 +9480,24 @@ pub const FuncGen = struct { |
| 9457 | | 9480 | |
| 9458 | // Function signature: fn (anyerror) bool | 9481 | // Function signature: fn (anyerror) bool |
| 9459 | | 9482 | |
| 9460 | const ret_llvm_ty = (try o.lowerType(Type.bool)).toLlvm(&o.builder); | 9483 | const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); |
| 9461 | const anyerror_llvm_ty = (try o.lowerType(Type.anyerror)).toLlvm(&o.builder); | 9484 | const llvm_fn = o.llvm_module.addFunction(lt_errors_fn_name, fn_type.toLlvm(&o.builder)); |
| 9462 | const param_types = [_]*llvm.Type{anyerror_llvm_ty}; | 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 | llvm_fn.setLinkage(.Internal); | 9494 | llvm_fn.setLinkage(.Internal); |
| 9467 | llvm_fn.setFunctionCallConv(.Fast); | 9495 | llvm_fn.setFunctionCallConv(.Fast); |
| 9468 | o.addCommonFnAttributes(llvm_fn); | 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 | return llvm_fn; | 9501 | return llvm_fn; |
| 9470 | } | 9502 | } |
| 9471 | | 9503 | |
| ... | @@ -9523,7 +9555,7 @@ pub const FuncGen = struct { | ... | @@ -9523,7 +9555,7 @@ pub const FuncGen = struct { |
| 9523 | const values = try self.gpa.alloc(*llvm.Value, mask_len); | 9555 | const values = try self.gpa.alloc(*llvm.Value, mask_len); |
| 9524 | defer self.gpa.free(values); | 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 | for (values, 0..) |*val, i| { | 9560 | for (values, 0..) |*val, i| { |
| 9529 | const elem = try mask.elemValue(mod, i); | 9561 | const elem = try mask.elemValue(mod, i); |
| ... | @@ -9565,9 +9597,9 @@ pub const FuncGen = struct { | ... | @@ -9565,9 +9597,9 @@ pub const FuncGen = struct { |
| 9565 | const llvm_result_ty = accum_init.typeOf(); | 9597 | const llvm_result_ty = accum_init.typeOf(); |
| 9566 | | 9598 | |
| 9567 | // Allocate and initialize our mutable variables | 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 | _ = self.builder.buildStore(llvm_usize_ty.constInt(0, .False), i_ptr); | 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 | _ = self.builder.buildStore(accum_init, accum_ptr); | 9603 | _ = self.builder.buildStore(accum_init, accum_ptr); |
| 9572 | | 9604 | |
| 9573 | // Setup the loop | 9605 | // Setup the loop |
| ... | @@ -9656,27 +9688,25 @@ pub const FuncGen = struct { | ... | @@ -9656,27 +9688,25 @@ pub const FuncGen = struct { |
| 9656 | | 9688 | |
| 9657 | // Reduction could not be performed with intrinsics. | 9689 | // Reduction could not be performed with intrinsics. |
| 9658 | // Use a manual loop over a softfloat call instead. | 9690 | // Use a manual loop over a softfloat call instead. |
| 9659 | var fn_name_buf: [64]u8 = undefined; | | |
| 9660 | const float_bits = scalar_ty.floatBits(target); | 9691 | const float_bits = scalar_ty.floatBits(target); |
| 9661 | const fn_name = switch (reduce.operation) { | 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 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), | 9694 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), |
| 9664 | }) catch unreachable, | 9695 | }), |
| 9665 | .Max => std.fmt.bufPrintZ(&fn_name_buf, "{s}fmax{s}", .{ | 9696 | .Max => try o.builder.fmt("{s}fmax{s}", .{ |
| 9666 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), | 9697 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), |
| 9667 | }) catch unreachable, | 9698 | }), |
| 9668 | .Add => std.fmt.bufPrintZ(&fn_name_buf, "__add{s}f3", .{ | 9699 | .Add => try o.builder.fmt("__add{s}f3", .{ |
| 9669 | compilerRtFloatAbbrev(float_bits), | 9700 | compilerRtFloatAbbrev(float_bits), |
| 9670 | }) catch unreachable, | 9701 | }), |
| 9671 | .Mul => std.fmt.bufPrintZ(&fn_name_buf, "__mul{s}f3", .{ | 9702 | .Mul => try o.builder.fmt("__mul{s}f3", .{ |
| 9672 | compilerRtFloatAbbrev(float_bits), | 9703 | compilerRtFloatAbbrev(float_bits), |
| 9673 | }) catch unreachable, | 9704 | }), |
| 9674 | else => unreachable, | 9705 | else => unreachable, |
| 9675 | }; | 9706 | }; |
| 9676 | | 9707 | |
| 9677 | const param_llvm_ty = (try o.lowerType(scalar_ty)).toLlvm(&o.builder); | 9708 | const param_llvm_ty = try o.lowerType(scalar_ty); |
| 9678 | const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty }; | 9709 | const libc_fn = try self.getLibcFunction(fn_name, &(.{param_llvm_ty} ** 2), param_llvm_ty); |
| 9679 | const libc_fn = try self.getLibcFunction(fn_name, &param_types, param_llvm_ty); | | |
| 9680 | const init_value = try o.lowerValue(.{ | 9710 | const init_value = try o.lowerValue(.{ |
| 9681 | .ty = scalar_ty, | 9711 | .ty = scalar_ty, |
| 9682 | .val = try mod.floatValue(scalar_ty, switch (reduce.operation) { | 9712 | .val = try mod.floatValue(scalar_ty, switch (reduce.operation) { |
| ... | @@ -9701,7 +9731,7 @@ pub const FuncGen = struct { | ... | @@ -9701,7 +9731,7 @@ pub const FuncGen = struct { |
| 9701 | | 9731 | |
| 9702 | switch (result_ty.zigTypeTag(mod)) { | 9732 | switch (result_ty.zigTypeTag(mod)) { |
| 9703 | .Vector => { | 9733 | .Vector => { |
| 9704 | const llvm_u32 = self.context.intType(32); | 9734 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 9705 | | 9735 | |
| 9706 | var vector = llvm_result_ty.getUndef(); | 9736 | var vector = llvm_result_ty.getUndef(); |
| 9707 | for (elements, 0..) |elem, i| { | 9737 | for (elements, 0..) |elem, i| { |
| ... | @@ -9716,7 +9746,7 @@ pub const FuncGen = struct { | ... | @@ -9716,7 +9746,7 @@ pub const FuncGen = struct { |
| 9716 | const struct_obj = mod.typeToStruct(result_ty).?; | 9746 | const struct_obj = mod.typeToStruct(result_ty).?; |
| 9717 | assert(struct_obj.haveLayout()); | 9747 | assert(struct_obj.haveLayout()); |
| 9718 | const big_bits = struct_obj.backing_int_ty.bitSize(mod); | 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 | const fields = struct_obj.fields.values(); | 9750 | const fields = struct_obj.fields.values(); |
| 9721 | comptime assert(Type.packed_struct_layout_version == 2); | 9751 | comptime assert(Type.packed_struct_layout_version == 2); |
| 9722 | var running_int: *llvm.Value = int_llvm_ty.constNull(); | 9752 | var running_int: *llvm.Value = int_llvm_ty.constNull(); |
| ... | @@ -9727,7 +9757,7 @@ pub const FuncGen = struct { | ... | @@ -9727,7 +9757,7 @@ pub const FuncGen = struct { |
| 9727 | | 9757 | |
| 9728 | const non_int_val = try self.resolveInst(elem); | 9758 | const non_int_val = try self.resolveInst(elem); |
| 9729 | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); | 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 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) | 9761 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9732 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") | 9762 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9733 | else | 9763 | else |
| ... | @@ -9745,10 +9775,10 @@ pub const FuncGen = struct { | ... | @@ -9745,10 +9775,10 @@ pub const FuncGen = struct { |
| 9745 | } | 9775 | } |
| 9746 | | 9776 | |
| 9747 | if (isByRef(result_ty, mod)) { | 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 | // TODO in debug builds init to undef so that the padding will be 0xaa | 9779 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 9750 | // even if we fully populate the fields. | 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 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; | 9783 | var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined }; |
| 9754 | for (elements, 0..) |elem, i| { | 9784 | for (elements, 0..) |elem, i| { |
| ... | @@ -9786,7 +9816,7 @@ pub const FuncGen = struct { | ... | @@ -9786,7 +9816,7 @@ pub const FuncGen = struct { |
| 9786 | assert(isByRef(result_ty, mod)); | 9816 | assert(isByRef(result_ty, mod)); |
| 9787 | | 9817 | |
| 9788 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); | 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 | const array_info = result_ty.arrayInfo(mod); | 9821 | const array_info = result_ty.arrayInfo(mod); |
| 9792 | const elem_ptr_ty = try mod.ptrType(.{ | 9822 | const elem_ptr_ty = try mod.ptrType(.{ |
| ... | @@ -9834,11 +9864,11 @@ pub const FuncGen = struct { | ... | @@ -9834,11 +9864,11 @@ pub const FuncGen = struct { |
| 9834 | | 9864 | |
| 9835 | if (union_obj.layout == .Packed) { | 9865 | if (union_obj.layout == .Packed) { |
| 9836 | const big_bits = union_ty.bitSize(mod); | 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 | const field = union_obj.fields.values()[extra.field_index]; | 9868 | const field = union_obj.fields.values()[extra.field_index]; |
| 9839 | const non_int_val = try self.resolveInst(extra.init); | 9869 | const non_int_val = try self.resolveInst(extra.init); |
| 9840 | const ty_bit_size = @as(u16, @intCast(field.ty.bitSize(mod))); | 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 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) | 9872 | const small_int_val = if (field.ty.isPtrAtRuntime(mod)) |
| 9843 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") | 9873 | self.builder.buildPtrToInt(non_int_val, small_int_ty, "") |
| 9844 | else | 9874 | else |
| ... | @@ -9866,51 +9896,47 @@ pub const FuncGen = struct { | ... | @@ -9866,51 +9896,47 @@ pub const FuncGen = struct { |
| 9866 | // necessarily match the format that we need, depending on which tag is active. | 9896 | // necessarily match the format that we need, depending on which tag is active. |
| 9867 | // We must construct the correct unnamed struct type here, in order to then set | 9897 | // We must construct the correct unnamed struct type here, in order to then set |
| 9868 | // the fields appropriately. | 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 | const llvm_payload = try self.resolveInst(extra.init); | 9900 | const llvm_payload = try self.resolveInst(extra.init); |
| 9871 | assert(union_obj.haveFieldTypes()); | 9901 | assert(union_obj.haveFieldTypes()); |
| 9872 | const field = union_obj.fields.values()[extra.field_index]; | 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 | const field_size = field.ty.abiSize(mod); | 9904 | const field_size = field.ty.abiSize(mod); |
| 9875 | const field_align = field.normalAlignment(mod); | 9905 | const field_align = field.normalAlignment(mod); |
| 9876 | | 9906 | |
| 9877 | const llvm_union_ty = t: { | 9907 | const llvm_union_ty = (t: { |
| 9878 | const payload = p: { | 9908 | const payload_ty = p: { |
| 9879 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) { | 9909 | if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 9880 | const padding_len = @as(c_uint, @intCast(layout.payload_size)); | 9910 | const padding_len = layout.payload_size; |
| 9881 | break :p self.context.intType(8).arrayType(padding_len); | 9911 | break :p try o.builder.arrayType(padding_len, .i8); |
| 9882 | } | 9912 | } |
| 9883 | if (field_size == layout.payload_size) { | 9913 | if (field_size == layout.payload_size) { |
| 9884 | break :p field_llvm_ty; | 9914 | break :p field_llvm_ty; |
| 9885 | } | 9915 | } |
| 9886 | const padding_len = @as(c_uint, @intCast(layout.payload_size - field_size)); | 9916 | const padding_len = layout.payload_size - field_size; |
| 9887 | const fields: [2]*llvm.Type = .{ | 9917 | break :p try o.builder.structType(.@"packed", &.{ |
| 9888 | field_llvm_ty, self.context.intType(8).arrayType(padding_len), | 9918 | field_llvm_ty, try o.builder.arrayType(padding_len, .i8), |
| 9889 | }; | 9919 | }); |
| 9890 | break :p self.context.structType(&fields, fields.len, .True); | | |
| 9891 | }; | 9920 | }; |
| 9892 | if (layout.tag_size == 0) { | 9921 | if (layout.tag_size == 0) break :t try o.builder.structType(.normal, &.{payload_ty}); |
| 9893 | const fields: [1]*llvm.Type = .{payload}; | 9922 | const tag_ty = try o.lowerType(union_obj.tag_ty); |
| 9894 | break :t self.context.structType(&fields, fields.len, .False); | 9923 | var fields: [3]Builder.Type = undefined; |
| 9895 | } | 9924 | var fields_len: usize = 2; |
| 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; | | |
| 9899 | if (layout.tag_align >= layout.payload_align) { | 9925 | if (layout.tag_align >= layout.payload_align) { |
| 9900 | fields = .{ tag_llvm_ty, payload, undefined }; | 9926 | fields = .{ tag_ty, payload_ty, undefined }; |
| 9901 | } else { | 9927 | } else { |
| 9902 | fields = .{ payload, tag_llvm_ty, undefined }; | 9928 | fields = .{ payload_ty, tag_ty, undefined }; |
| 9903 | } | 9929 | } |
| 9904 | if (layout.padding != 0) { | 9930 | if (layout.padding != 0) { |
| 9905 | fields[2] = self.context.intType(8).arrayType(layout.padding); | 9931 | fields[fields_len] = try o.builder.arrayType(layout.padding, .i8); |
| 9906 | fields_len = 3; | 9932 | fields_len += 1; |
| 9907 | } | 9933 | } |
| 9908 | break :t self.context.structType(&fields, fields_len, .False); | 9934 | break :t try o.builder.structType(.normal, fields[0..fields_len]); |
| 9909 | }; | 9935 | }).toLlvm(&o.builder); |
| 9910 | | 9936 | |
| 9911 | // Now we follow the layout as expressed above with GEP instructions to set the | 9937 | // Now we follow the layout as expressed above with GEP instructions to set the |
| 9912 | // tag and the payload. | 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 | const field_ptr_ty = try mod.ptrType(.{ | 9941 | const field_ptr_ty = try mod.ptrType(.{ |
| 9916 | .child = field.ty.toIntern(), | 9942 | .child = field.ty.toIntern(), |
| ... | @@ -9996,22 +10022,16 @@ pub const FuncGen = struct { | ... | @@ -9996,22 +10022,16 @@ pub const FuncGen = struct { |
| 9996 | .data => {}, | 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 | const llvm_fn_name = "llvm.prefetch.p0"; | 10025 | const llvm_fn_name = "llvm.prefetch.p0"; |
| 10003 | const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { | 10026 | const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { |
| 10004 | // declare void @llvm.prefetch(i8*, i32, i32, i32) | 10027 | // declare void @llvm.prefetch(i8*, i32, i32, i32) |
| 10005 | const llvm_void = self.context.voidType(); | 10028 | const fn_type = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal); |
| 10006 | const param_types = [_]*llvm.Type{ | 10029 | break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); |
| 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); | | |
| 10011 | }; | 10030 | }; |
| 10012 | | 10031 | |
| 10013 | const ptr = try self.resolveInst(prefetch.ptr); | 10032 | const ptr = try self.resolveInst(prefetch.ptr); |
| 10014 | | 10033 | |
| | 10034 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10015 | const params = [_]*llvm.Value{ | 10035 | const params = [_]*llvm.Value{ |
| 10016 | ptr, | 10036 | ptr, |
| 10017 | llvm_u32.constInt(@intFromEnum(prefetch.rw), .False), | 10037 | llvm_u32.constInt(@intFromEnum(prefetch.rw), .False), |
| ... | @@ -10033,7 +10053,7 @@ pub const FuncGen = struct { | ... | @@ -10033,7 +10053,7 @@ pub const FuncGen = struct { |
| 10033 | } | 10053 | } |
| 10034 | | 10054 | |
| 10035 | fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !?*llvm.Value { | 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 | const llvm_fn_name = switch (dimension) { | 10058 | const llvm_fn_name = switch (dimension) { |
| 10039 | 0 => basename ++ ".x", | 10059 | 0 => basename ++ ".x", |
| ... | @@ -10043,7 +10063,7 @@ pub const FuncGen = struct { | ... | @@ -10043,7 +10063,7 @@ pub const FuncGen = struct { |
| 10043 | }; | 10063 | }; |
| 10044 | | 10064 | |
| 10045 | const args: [0]*llvm.Value = .{}; | 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 | return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 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,14 +10084,14 @@ pub const FuncGen = struct { |
| 10064 | | 10084 | |
| 10065 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 10085 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 10066 | const dimension = pl_op.payload; | 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 | if (dimension >= 3) { | 10088 | if (dimension >= 3) { |
| 10069 | return llvm_u32.constInt(1, .False); | 10089 | return llvm_u32.constInt(1, .False); |
| 10070 | } | 10090 | } |
| 10071 | | 10091 | |
| 10072 | // Fetch the dispatch pointer, which points to this structure: | 10092 | // Fetch the dispatch pointer, which points to this structure: |
| 10073 | // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913 | 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 | const args: [0]*llvm.Value = .{}; | 10095 | const args: [0]*llvm.Value = .{}; |
| 10076 | const dispatch_ptr = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); | 10096 | const dispatch_ptr = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); |
| 10077 | dispatch_ptr.setAlignment(4); | 10097 | dispatch_ptr.setAlignment(4); |
| ... | @@ -10080,7 +10100,7 @@ pub const FuncGen = struct { | ... | @@ -10080,7 +10100,7 @@ pub const FuncGen = struct { |
| 10080 | // Just treat the dispatch pointer as an array of u16 to keep things simple. | 10100 | // Just treat the dispatch pointer as an array of u16 to keep things simple. |
| 10081 | const offset = 2 + dimension; | 10101 | const offset = 2 + dimension; |
| 10082 | const index = [_]*llvm.Value{llvm_u32.constInt(offset, .False)}; | 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 | const workgroup_size_ptr = self.builder.buildInBoundsGEP(llvm_u16, dispatch_ptr, &index, index.len, ""); | 10104 | const workgroup_size_ptr = self.builder.buildInBoundsGEP(llvm_u16, dispatch_ptr, &index, index.len, ""); |
| 10085 | const workgroup_size = self.builder.buildLoad(llvm_u16, workgroup_size_ptr, ""); | 10105 | const workgroup_size = self.builder.buildLoad(llvm_u16, workgroup_size_ptr, ""); |
| 10086 | workgroup_size.setAlignment(2); | 10106 | workgroup_size.setAlignment(2); |
| ... | @@ -10126,7 +10146,7 @@ pub const FuncGen = struct { | ... | @@ -10126,7 +10146,7 @@ pub const FuncGen = struct { |
| 10126 | opt_handle: *llvm.Value, | 10146 | opt_handle: *llvm.Value, |
| 10127 | is_by_ref: bool, | 10147 | is_by_ref: bool, |
| 10128 | ) *llvm.Value { | 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 | const field = b: { | 10150 | const field = b: { |
| 10131 | if (is_by_ref) { | 10151 | if (is_by_ref) { |
| 10132 | const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); | 10152 | const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); |
| ... | @@ -10180,12 +10200,12 @@ pub const FuncGen = struct { | ... | @@ -10180,12 +10200,12 @@ pub const FuncGen = struct { |
| 10180 | ) !?*llvm.Value { | 10200 | ) !?*llvm.Value { |
| 10181 | const o = self.dg.object; | 10201 | const o = self.dg.object; |
| 10182 | const optional_llvm_ty = (try o.lowerType(optional_ty)).toLlvm(&o.builder); | 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 | const mod = o.module; | 10204 | const mod = o.module; |
| 10185 | | 10205 | |
| 10186 | if (isByRef(optional_ty, mod)) { | 10206 | if (isByRef(optional_ty, mod)) { |
| 10187 | const payload_alignment = optional_ty.abiAlignment(mod); | 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 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); | 10211 | const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); |
| ... | @@ -10233,7 +10253,7 @@ pub const FuncGen = struct { | ... | @@ -10233,7 +10253,7 @@ pub const FuncGen = struct { |
| 10233 | // Offset our operand pointer by the correct number of bytes. | 10253 | // Offset our operand pointer by the correct number of bytes. |
| 10234 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod); | 10254 | const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod); |
| 10235 | if (byte_offset == 0) return struct_ptr; | 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 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); | 10257 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10238 | const llvm_index = llvm_usize.constInt(byte_offset, .False); | 10258 | const llvm_index = llvm_usize.constInt(byte_offset, .False); |
| 10239 | const indices: [1]*llvm.Value = .{llvm_index}; | 10259 | const indices: [1]*llvm.Value = .{llvm_index}; |
| ... | @@ -10249,7 +10269,7 @@ pub const FuncGen = struct { | ... | @@ -10249,7 +10269,7 @@ pub const FuncGen = struct { |
| 10249 | // end of the struct. Treat our struct pointer as an array of two and get | 10269 | // end of the struct. Treat our struct pointer as an array of two and get |
| 10250 | // the index to the element at index `1` to get a pointer to the end of | 10270 | // the index to the element at index `1` to get a pointer to the end of |
| 10251 | // the struct. | 10271 | // the struct. |
| 10252 | const llvm_u32 = self.context.intType(32); | 10272 | const llvm_u32 = Builder.Type.i32.toLlvm(&o.builder); |
| 10253 | const llvm_index = llvm_u32.constInt(@intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); | 10273 | const llvm_index = llvm_u32.constInt(@intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); |
| 10254 | const indices: [1]*llvm.Value = .{llvm_index}; | 10274 | const indices: [1]*llvm.Value = .{llvm_index}; |
| 10255 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); | 10275 | return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); |
| ... | @@ -10268,11 +10288,14 @@ pub const FuncGen = struct { | ... | @@ -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 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); | 10293 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); |
| 10273 | assert(id != 0); | 10294 | assert(id != 0); |
| 10274 | const o = fg.dg.object; | 10295 | const llvm_types = try o.gpa.alloc(*llvm.Type, types.len); |
| 10275 | return o.llvm_module.getIntrinsicDeclaration(id, types.ptr, 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 | /// Load a by-ref type by constructing a new alloca and performing a memcpy. | 10301 | /// Load a by-ref type by constructing a new alloca and performing a memcpy. |
| ... | @@ -10287,8 +10310,8 @@ pub const FuncGen = struct { | ... | @@ -10287,8 +10310,8 @@ pub const FuncGen = struct { |
| 10287 | const mod = o.module; | 10310 | const mod = o.module; |
| 10288 | const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder); | 10311 | const pointee_llvm_ty = (try o.lowerType(pointee_type)).toLlvm(&o.builder); |
| 10289 | const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod)); | 10312 | const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod)); |
| 10290 | const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align); | 10313 | const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); |
| 10291 | const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits); | 10314 | const llvm_usize = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10292 | const size_bytes = pointee_type.abiSize(mod); | 10315 | const size_bytes = pointee_type.abiSize(mod); |
| 10293 | _ = fg.builder.buildMemCpy( | 10316 | _ = fg.builder.buildMemCpy( |
| 10294 | result_ptr, | 10317 | result_ptr, |
| ... | @@ -10317,7 +10340,7 @@ pub const FuncGen = struct { | ... | @@ -10317,7 +10340,7 @@ pub const FuncGen = struct { |
| 10317 | | 10340 | |
| 10318 | assert(info.flags.vector_index != .runtime); | 10341 | assert(info.flags.vector_index != .runtime); |
| 10319 | if (info.flags.vector_index != .none) { | 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 | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); | 10344 | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 10322 | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); | 10345 | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); |
| 10323 | | 10346 | |
| ... | @@ -10339,7 +10362,7 @@ pub const FuncGen = struct { | ... | @@ -10339,7 +10362,7 @@ pub const FuncGen = struct { |
| 10339 | return llvm_inst; | 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 | const containing_int = self.builder.buildLoad(int_elem_ty, ptr, ""); | 10366 | const containing_int = self.builder.buildLoad(int_elem_ty, ptr, ""); |
| 10344 | containing_int.setAlignment(ptr_alignment); | 10367 | containing_int.setAlignment(ptr_alignment); |
| 10345 | containing_int.setVolatile(ptr_volatile); | 10368 | containing_int.setVolatile(ptr_volatile); |
| ... | @@ -10351,9 +10374,9 @@ pub const FuncGen = struct { | ... | @@ -10351,9 +10374,9 @@ pub const FuncGen = struct { |
| 10351 | | 10374 | |
| 10352 | if (isByRef(elem_ty, mod)) { | 10375 | if (isByRef(elem_ty, mod)) { |
| 10353 | const result_align = elem_ty.abiAlignment(mod); | 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 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 10380 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 10358 | const store_inst = self.builder.buildStore(truncated_int, result_ptr); | 10381 | const store_inst = self.builder.buildStore(truncated_int, result_ptr); |
| 10359 | store_inst.setAlignment(result_align); | 10382 | store_inst.setAlignment(result_align); |
| ... | @@ -10361,13 +10384,13 @@ pub const FuncGen = struct { | ... | @@ -10361,13 +10384,13 @@ pub const FuncGen = struct { |
| 10361 | } | 10384 | } |
| 10362 | | 10385 | |
| 10363 | if (elem_ty.zigTypeTag(mod) == .Float or elem_ty.zigTypeTag(mod) == .Vector) { | 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 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 10388 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 10366 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); | 10389 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 10367 | } | 10390 | } |
| 10368 | | 10391 | |
| 10369 | if (elem_ty.isPtrAtRuntime(mod)) { | 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 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); | 10394 | const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); |
| 10372 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); | 10395 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 10373 | } | 10396 | } |
| ... | @@ -10394,7 +10417,7 @@ pub const FuncGen = struct { | ... | @@ -10394,7 +10417,7 @@ pub const FuncGen = struct { |
| 10394 | | 10417 | |
| 10395 | assert(info.flags.vector_index != .runtime); | 10418 | assert(info.flags.vector_index != .runtime); |
| 10396 | if (info.flags.vector_index != .none) { | 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 | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); | 10421 | const vec_elem_ty = (try o.lowerType(elem_ty)).toLlvm(&o.builder); |
| 10399 | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); | 10422 | const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); |
| 10400 | | 10423 | |
| ... | @@ -10412,7 +10435,7 @@ pub const FuncGen = struct { | ... | @@ -10412,7 +10435,7 @@ pub const FuncGen = struct { |
| 10412 | } | 10435 | } |
| 10413 | | 10436 | |
| 10414 | if (info.packed_offset.host_size != 0) { | 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 | const containing_int = self.builder.buildLoad(int_elem_ty, ptr, ""); | 10439 | const containing_int = self.builder.buildLoad(int_elem_ty, ptr, ""); |
| 10417 | assert(ordering == .NotAtomic); | 10440 | assert(ordering == .NotAtomic); |
| 10418 | containing_int.setAlignment(ptr_alignment); | 10441 | containing_int.setAlignment(ptr_alignment); |
| ... | @@ -10422,7 +10445,7 @@ pub const FuncGen = struct { | ... | @@ -10422,7 +10445,7 @@ pub const FuncGen = struct { |
| 10422 | const shift_amt = containing_int_ty.constInt(info.packed_offset.bit_offset, .False); | 10445 | const shift_amt = containing_int_ty.constInt(info.packed_offset.bit_offset, .False); |
| 10423 | // Convert to equally-sized integer type in order to perform the bit | 10446 | // Convert to equally-sized integer type in order to perform the bit |
| 10424 | // operations on the value to store | 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 | const value_bits = if (elem_ty.isPtrAtRuntime(mod)) | 10449 | const value_bits = if (elem_ty.isPtrAtRuntime(mod)) |
| 10427 | self.builder.buildPtrToInt(elem, value_bits_type, "") | 10450 | self.builder.buildPtrToInt(elem, value_bits_type, "") |
| 10428 | else | 10451 | else |
| ... | @@ -10458,20 +10481,19 @@ pub const FuncGen = struct { | ... | @@ -10458,20 +10481,19 @@ pub const FuncGen = struct { |
| 10458 | ptr_alignment, | 10481 | ptr_alignment, |
| 10459 | elem, | 10482 | elem, |
| 10460 | elem_ty.abiAlignment(mod), | 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 | info.flags.is_volatile, | 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 | const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; | 10490 | const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; |
| 10468 | const o = fg.dg.object; | 10491 | const o = fg.dg.object; |
| 10469 | const target = o.module.getTarget(); | 10492 | const usize_llvm_ty = (try o.lowerType(Type.usize)).toLlvm(&o.builder); |
| 10470 | const usize_llvm_ty = fg.context.intType(target.ptrBitWidth()); | | |
| 10471 | const zero = usize_llvm_ty.constInt(0, .False); | 10493 | const zero = usize_llvm_ty.constInt(0, .False); |
| 10472 | const req = usize_llvm_ty.constInt(VG_USERREQ__MAKE_MEM_UNDEFINED, .False); | 10494 | const req = usize_llvm_ty.constInt(VG_USERREQ__MAKE_MEM_UNDEFINED, .False); |
| 10473 | const ptr_as_usize = fg.builder.buildPtrToInt(ptr, usize_llvm_ty, ""); | 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 | fn valgrindClientRequest( | 10499 | fn valgrindClientRequest( |
| ... | @@ -10483,18 +10505,19 @@ pub const FuncGen = struct { | ... | @@ -10483,18 +10505,19 @@ pub const FuncGen = struct { |
| 10483 | a3: *llvm.Value, | 10505 | a3: *llvm.Value, |
| 10484 | a4: *llvm.Value, | 10506 | a4: *llvm.Value, |
| 10485 | a5: *llvm.Value, | 10507 | a5: *llvm.Value, |
| 10486 | ) *llvm.Value { | 10508 | ) Allocator.Error!*llvm.Value { |
| 10487 | const o = fg.dg.object; | 10509 | const o = fg.dg.object; |
| 10488 | const mod = o.module; | 10510 | const mod = o.module; |
| 10489 | const target = mod.getTarget(); | 10511 | const target = mod.getTarget(); |
| 10490 | if (!target_util.hasValgrindSupport(target)) return default_value; | 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 | const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod))); | 10516 | const usize_alignment = @as(c_uint, @intCast(Type.usize.abiSize(mod))); |
| 10494 | | 10517 | |
| 10495 | const array_llvm_ty = usize_llvm_ty.arrayType(6); | 10518 | const array_llvm_ty = usize_llvm_ty.arrayType(6); |
| 10496 | const array_ptr = fg.valgrind_client_request_array orelse a: { | 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 | fg.valgrind_client_request_array = array_ptr; | 10521 | fg.valgrind_client_request_array = array_ptr; |
| 10499 | break :a array_ptr; | 10522 | break :a array_ptr; |
| 10500 | }; | 10523 | }; |
| ... | @@ -10540,10 +10563,9 @@ pub const FuncGen = struct { | ... | @@ -10540,10 +10563,9 @@ pub const FuncGen = struct { |
| 10540 | else => unreachable, | 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 | const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, ""); | 10567 | const array_ptr_as_usize = fg.builder.buildPtrToInt(array_ptr, usize_llvm_ty, ""); |
| 10544 | const args = [_]*llvm.Value{ array_ptr_as_usize, default_value }; | 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 | const asm_fn = llvm.getInlineAsm( | 10569 | const asm_fn = llvm.getInlineAsm( |
| 10548 | fn_llvm_ty, | 10570 | fn_llvm_ty, |
| 10549 | arch_specific.template.ptr, | 10571 | arch_specific.template.ptr, |
| ... | @@ -11200,7 +11222,6 @@ const ParamTypeIterator = struct { | ... | @@ -11200,7 +11222,6 @@ const ParamTypeIterator = struct { |
| 11200 | llvm_index: u32, | 11222 | llvm_index: u32, |
| 11201 | types_len: u32, | 11223 | types_len: u32, |
| 11202 | types_buffer: [8]Builder.Type, | 11224 | types_buffer: [8]Builder.Type, |
| 11203 | llvm_types_buffer: [8]*llvm.Type, | | |
| 11204 | byval_attr: bool, | 11225 | byval_attr: bool, |
| 11205 | | 11226 | |
| 11206 | const Lowering = union(enum) { | 11227 | const Lowering = union(enum) { |
| ... | @@ -11298,7 +11319,6 @@ const ParamTypeIterator = struct { | ... | @@ -11298,7 +11319,6 @@ const ParamTypeIterator = struct { |
| 11298 | .integer => { | 11319 | .integer => { |
| 11299 | it.types_len = 1; | 11320 | it.types_len = 1; |
| 11300 | it.types_buffer[0] = .i64; | 11321 | it.types_buffer[0] = .i64; |
| 11301 | it.llvm_types_buffer[0] = it.types_buffer[0].toLlvm(&it.object.builder); | | |
| 11302 | return .multiple_llvm_types; | 11322 | return .multiple_llvm_types; |
| 11303 | }, | 11323 | }, |
| 11304 | .double_integer => return Lowering{ .i64_array = 2 }, | 11324 | .double_integer => return Lowering{ .i64_array = 2 }, |
| ... | @@ -11408,31 +11428,22 @@ const ParamTypeIterator = struct { | ... | @@ -11408,31 +11428,22 @@ const ParamTypeIterator = struct { |
| 11408 | } | 11428 | } |
| 11409 | var types_index: u32 = 0; | 11429 | var types_index: u32 = 0; |
| 11410 | var types_buffer: [8]Builder.Type = undefined; | 11430 | var types_buffer: [8]Builder.Type = undefined; |
| 11411 | var llvm_types_buffer: [8]*llvm.Type = undefined; | | |
| 11412 | for (classes) |class| { | 11431 | for (classes) |class| { |
| 11413 | switch (class) { | 11432 | switch (class) { |
| 11414 | .integer => { | 11433 | .integer => { |
| 11415 | types_buffer[types_index] = .i64; | 11434 | types_buffer[types_index] = .i64; |
| 11416 | llvm_types_buffer[types_index] = | | |
| 11417 | types_buffer[types_index].toLlvm(&it.object.builder); | | |
| 11418 | types_index += 1; | 11435 | types_index += 1; |
| 11419 | }, | 11436 | }, |
| 11420 | .sse, .sseup => { | 11437 | .sse, .sseup => { |
| 11421 | types_buffer[types_index] = .double; | 11438 | types_buffer[types_index] = .double; |
| 11422 | llvm_types_buffer[types_index] = | | |
| 11423 | types_buffer[types_index].toLlvm(&it.object.builder); | | |
| 11424 | types_index += 1; | 11439 | types_index += 1; |
| 11425 | }, | 11440 | }, |
| 11426 | .float => { | 11441 | .float => { |
| 11427 | types_buffer[types_index] = .float; | 11442 | types_buffer[types_index] = .float; |
| 11428 | llvm_types_buffer[types_index] = | | |
| 11429 | types_buffer[types_index].toLlvm(&it.object.builder); | | |
| 11430 | types_index += 1; | 11443 | types_index += 1; |
| 11431 | }, | 11444 | }, |
| 11432 | .float_combine => { | 11445 | .float_combine => { |
| 11433 | types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); | 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 | types_index += 1; | 11447 | types_index += 1; |
| 11437 | }, | 11448 | }, |
| 11438 | .x87 => { | 11449 | .x87 => { |
| ... | @@ -11457,7 +11468,6 @@ const ParamTypeIterator = struct { | ... | @@ -11457,7 +11468,6 @@ const ParamTypeIterator = struct { |
| 11457 | } | 11468 | } |
| 11458 | it.types_len = types_index; | 11469 | it.types_len = types_index; |
| 11459 | it.types_buffer = types_buffer; | 11470 | it.types_buffer = types_buffer; |
| 11460 | it.llvm_types_buffer = llvm_types_buffer; | | |
| 11461 | it.llvm_index += types_index; | 11471 | it.llvm_index += types_index; |
| 11462 | it.zig_index += 1; | 11472 | it.zig_index += 1; |
| 11463 | return .multiple_llvm_types; | 11473 | return .multiple_llvm_types; |
| ... | @@ -11472,7 +11482,6 @@ fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTyp | ... | @@ -11472,7 +11482,6 @@ fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTyp |
| 11472 | .llvm_index = 0, | 11482 | .llvm_index = 0, |
| 11473 | .types_len = 0, | 11483 | .types_len = 0, |
| 11474 | .types_buffer = undefined, | 11484 | .types_buffer = undefined, |
| 11475 | .llvm_types_buffer = undefined, | | |
| 11476 | .byval_attr = false, | 11485 | .byval_attr = false, |
| 11477 | }; | 11486 | }; |
| 11478 | } | 11487 | } |
| ... | @@ -11740,51 +11749,6 @@ fn compilerRtIntBits(bits: u16) u16 { | ... | @@ -11740,51 +11749,6 @@ fn compilerRtIntBits(bits: u16) u16 { |
| 11740 | return bits; | 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 | fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 { | 11752 | fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 { |
| 11789 | return @intFromBool(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod)); | 11753 | return @intFromBool(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod)); |
| 11790 | } | 11754 | } |