authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-05 23:13:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-06 11:43:06-07:00
logd136cd3202711bf6ad11a6f62115cfce0d6e88f1
treed6b64473c62a98af39d8748a94b009216b29a97f
parentedb3adaa33f943d0c64071fbf9d43aadadaa1e95

LLVM: rework the previous commit

Idiomatic Zig, use const instead of var, simplify the logic.

2 files changed, 55 insertions(+), 96 deletions(-)

src/codegen/llvm.zig+47-96
......@@ -4229,61 +4229,20 @@ pub const FuncGen = struct {
42294229 return self.builder.buildInsertValue(partial, len, 1, "");
42304230 }
42314231
4232 inline fn isPowerOfTwo(bits: u64) bool {
4233 return bits != 0 and ((bits & (~bits + 1)) == bits);
4234 }
4235
4236 fn intTypeFromBitsAndSignRounded(self: *FuncGen, bits: u16, signed: bool) error{OutOfMemory}!Type {
4237 const next_pow_two = math.log2_int_ceil(u16, bits);
4238 const rounded_bits = @as(u32, 1) << next_pow_two;
4239 return switch (rounded_bits) {
4240 8, 16, 32 => if (signed) Type.initTag(.i32) else Type.initTag(.u32),
4241 64 => if (signed) Type.initTag(.i64) else Type.initTag(.u64),
4242 128 => if (signed) Type.initTag(.i128) else Type.initTag(.u128),
4243 else => |big| if (signed)
4244 Type.Tag.int_signed.create(
4245 self.dg.object.type_map_arena.allocator(),
4246 @intCast(u16, big),
4247 )
4248 else
4249 Type.Tag.int_unsigned.create(
4250 self.dg.object.type_map_arena.allocator(),
4251 @intCast(u16, big),
4252 ),
4253 };
4254 }
4255
42564232 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
42574233 if (self.liveness.isUnused(inst))
42584234 return null;
42594235
4260 const target = self.dg.module.getTarget();
42614236 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
42624237
4263 var operand = try self.resolveInst(ty_op.operand);
4264 var operand_ty = self.air.typeOf(ty_op.operand);
4265 var operand_scalar_ty = operand_ty.scalarType();
4266
4267 {
4268 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));
4269 const is_signed = operand_scalar_ty.isSignedInt();
4270
4271 if (!isPowerOfTwo(operand_bits) or operand_bits < 32) {
4272 const wider_ty = try self.intTypeFromBitsAndSignRounded(operand_bits, is_signed);
4273 const wider_llvm_ty = try self.dg.llvmType(wider_ty);
4274 if (is_signed) {
4275 operand = self.builder.buildSExt(operand, wider_llvm_ty, "");
4276 } else {
4277 operand = self.builder.buildZExt(operand, wider_llvm_ty, "");
4278 }
4279 operand_ty = wider_ty;
4280 operand_scalar_ty = operand_ty.scalarType();
4281 }
4282 }
4238 const operand = try self.resolveInst(ty_op.operand);
4239 const operand_ty = self.air.typeOf(ty_op.operand);
4240 const operand_scalar_ty = operand_ty.scalarType();
42834241
42844242 const dest_ty = self.air.typeOfIndex(inst);
42854243 const dest_scalar_ty = dest_ty.scalarType();
42864244 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
4245 const target = self.dg.module.getTarget();
42874246
42884247 if (intrinsicsAllowed(dest_scalar_ty, target)) {
42894248 if (operand_scalar_ty.isSignedInt()) {
......@@ -4294,27 +4253,28 @@ pub const FuncGen = struct {
42944253 }
42954254
42964255 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));
4297 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(operand_bits);
4298
4256 const rt_int_bits = compilerRtIntBits(operand_bits);
4257 const rt_int_ty = self.context.intType(rt_int_bits);
4258 const extended = e: {
4259 if (operand_scalar_ty.isSignedInt()) {
4260 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");
4261 } else {
4262 break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, "");
4263 }
4264 };
42994265 const dest_bits = dest_scalar_ty.floatBits(target);
4266 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
43004267 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);
4301
4268 const sign_prefix = if (operand_scalar_ty.isSignedInt()) "" else "un";
43024269 var fn_name_buf: [64]u8 = undefined;
4303 const fn_name = if (operand_scalar_ty.isSignedInt())
4304 std.fmt.bufPrintZ(&fn_name_buf, "__float{s}i{s}f", .{
4305 compiler_rt_operand_abbrev,
4306 compiler_rt_dest_abbrev,
4307 }) catch unreachable
4308 else
4309 std.fmt.bufPrintZ(&fn_name_buf, "__floatun{s}i{s}f", .{
4310 compiler_rt_operand_abbrev,
4311 compiler_rt_dest_abbrev,
4312 }) catch unreachable;
4313
4314 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4315 const param_types = [1]*const llvm.Type{operand_llvm_ty};
4270 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{
4271 sign_prefix,
4272 compiler_rt_operand_abbrev,
4273 compiler_rt_dest_abbrev,
4274 }) catch unreachable;
4275 const param_types = [1]*const llvm.Type{rt_int_ty};
43164276 const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty);
4317 const params = [1]*const llvm.Value{operand};
4277 const params = [1]*const llvm.Value{extended};
43184278
43194279 return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
43204280 }
......@@ -4330,12 +4290,12 @@ pub const FuncGen = struct {
43304290 const operand_ty = self.air.typeOf(ty_op.operand);
43314291 const operand_scalar_ty = operand_ty.scalarType();
43324292
4333 var dest_ty = self.air.typeOfIndex(inst);
4334 var dest_scalar_ty = dest_ty.scalarType();
4293 const dest_ty = self.air.typeOfIndex(inst);
4294 const dest_scalar_ty = dest_ty.scalarType();
4295 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
43354296
43364297 if (intrinsicsAllowed(operand_scalar_ty, target)) {
43374298 // TODO set fast math flag
4338 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
43394299 if (dest_scalar_ty.isSignedInt()) {
43404300 return self.builder.buildFPToSI(operand, dest_llvm_ty, "");
43414301 } else {
......@@ -4343,52 +4303,34 @@ pub const FuncGen = struct {
43434303 }
43444304 }
43454305
4346 const needs_truncating = blk: {
4347 const dest_bits = @intCast(u16, dest_scalar_ty.bitSize(target));
4348
4349 if (!isPowerOfTwo(dest_bits) or dest_bits < 32) {
4350 dest_ty = try self.intTypeFromBitsAndSignRounded(dest_bits, dest_scalar_ty.isSignedInt());
4351 dest_scalar_ty = dest_ty.scalarType();
4352 break :blk true;
4353 }
4354
4355 break :blk false;
4356 };
4357
4358 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
4306 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target)));
4307 const libc_ret_ty = self.context.intType(rt_int_bits);
43594308
43604309 const operand_bits = operand_scalar_ty.floatBits(target);
43614310 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
43624311
4363 const dest_bits = @intCast(u16, dest_scalar_ty.bitSize(target));
4364 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(dest_bits);
4312 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);
4313 const sign_prefix = if (dest_scalar_ty.isSignedInt()) "" else "un";
43654314
43664315 var fn_name_buf: [64]u8 = undefined;
4367 const fn_name = if (dest_scalar_ty.isSignedInt())
4368 std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}f{s}i", .{
4369 compiler_rt_operand_abbrev,
4370 compiler_rt_dest_abbrev,
4371 }) catch unreachable
4372 else
4373 std.fmt.bufPrintZ(&fn_name_buf, "__fixun{s}f{s}i", .{
4374 compiler_rt_operand_abbrev,
4375 compiler_rt_dest_abbrev,
4376 }) catch unreachable;
4316 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{
4317 sign_prefix,
4318 compiler_rt_operand_abbrev,
4319 compiler_rt_dest_abbrev,
4320 }) catch unreachable;
43774321
43784322 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
43794323 const param_types = [1]*const llvm.Type{operand_llvm_ty};
4380 const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty);
4324 const libc_fn = self.getLibcFunction(fn_name, &param_types, libc_ret_ty);
43814325 const params = [1]*const llvm.Value{operand};
43824326
43834327 const result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
43844328
4385 if (needs_truncating) {
4386 const requested_ty = self.air.typeOfIndex(inst);
4387 const requested_llvm_ty = try self.dg.llvmType(requested_ty);
4388 return self.builder.buildTrunc(result, requested_llvm_ty, "");
4329 if (libc_ret_ty == dest_llvm_ty) {
4330 return result;
43894331 }
43904332
4391 return result;
4333 return self.builder.buildTrunc(result, dest_llvm_ty, "");
43924334 }
43934335
43944336 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {
......@@ -8448,3 +8390,12 @@ fn needDbgVarWorkaround(dg: *DeclGen, ty: Type) bool {
84488390 }
84498391 return false;
84508392}
8393
8394fn compilerRtIntBits(bits: u16) u16 {
8395 inline for (.{ 8, 16, 32, 64, 128 }) |b| {
8396 if (bits <= b) {
8397 return b;
8398 }
8399 }
8400 return bits;
8401}
src/codegen/llvm/bindings.zig+8
......@@ -476,6 +476,14 @@ pub const Builder = opaque {
476476 Name: [*:0]const u8,
477477 ) *const Value;
478478
479 pub const buildSExtOrBitCast = LLVMBuildSExtOrBitCast;
480 extern fn LLVMBuildSExtOrBitCast(
481 *const Builder,
482 Val: *const Value,
483 DestTy: *const Type,
484 Name: [*:0]const u8,
485 ) *const Value;
486
479487 pub const buildCall = ZigLLVMBuildCall;
480488 extern fn ZigLLVMBuildCall(
481489 *const Builder,