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 {...@@ -4229,61 +4229,20 @@ pub const FuncGen = struct {
4229 return self.builder.buildInsertValue(partial, len, 1, "");4229 return self.builder.buildInsertValue(partial, len, 1, "");
4230 }4230 }
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
4256 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {4232 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4257 if (self.liveness.isUnused(inst))4233 if (self.liveness.isUnused(inst))
4258 return null;4234 return null;
42594235
4260 const target = self.dg.module.getTarget();
4261 const ty_op = self.air.instructions.items(.data)[inst].ty_op;4236 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
42624237
4263 var operand = try self.resolveInst(ty_op.operand);4238 const operand = try self.resolveInst(ty_op.operand);
4264 var operand_ty = self.air.typeOf(ty_op.operand);4239 const operand_ty = self.air.typeOf(ty_op.operand);
4265 var operand_scalar_ty = operand_ty.scalarType();4240 const 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 }
42834241
4284 const dest_ty = self.air.typeOfIndex(inst);4242 const dest_ty = self.air.typeOfIndex(inst);
4285 const dest_scalar_ty = dest_ty.scalarType();4243 const dest_scalar_ty = dest_ty.scalarType();
4286 const dest_llvm_ty = try self.dg.llvmType(dest_ty);4244 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
4245 const target = self.dg.module.getTarget();
42874246
4288 if (intrinsicsAllowed(dest_scalar_ty, target)) {4247 if (intrinsicsAllowed(dest_scalar_ty, target)) {
4289 if (operand_scalar_ty.isSignedInt()) {4248 if (operand_scalar_ty.isSignedInt()) {
...@@ -4294,27 +4253,28 @@ pub const FuncGen = struct {...@@ -4294,27 +4253,28 @@ pub const FuncGen = struct {
4294 }4253 }
42954254
4296 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));4255 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));
4297 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(operand_bits);4256 const rt_int_bits = compilerRtIntBits(operand_bits);
42984257 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 };
4299 const dest_bits = dest_scalar_ty.floatBits(target);4265 const dest_bits = dest_scalar_ty.floatBits(target);
4266 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
4300 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);4267 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);
43014268 const sign_prefix = if (operand_scalar_ty.isSignedInt()) "" else "un";
4302 var fn_name_buf: [64]u8 = undefined;4269 var fn_name_buf: [64]u8 = undefined;
4303 const fn_name = if (operand_scalar_ty.isSignedInt())4270 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{
4304 std.fmt.bufPrintZ(&fn_name_buf, "__float{s}i{s}f", .{4271 sign_prefix,
4305 compiler_rt_operand_abbrev,4272 compiler_rt_operand_abbrev,
4306 compiler_rt_dest_abbrev,4273 compiler_rt_dest_abbrev,
4307 }) catch unreachable4274 }) catch unreachable;
4308 else4275 const param_types = [1]*const llvm.Type{rt_int_ty};
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};
4316 const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty);4276 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
4319 return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");4279 return self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
4320 }4280 }
...@@ -4330,12 +4290,12 @@ pub const FuncGen = struct {...@@ -4330,12 +4290,12 @@ pub const FuncGen = struct {
4330 const operand_ty = self.air.typeOf(ty_op.operand);4290 const operand_ty = self.air.typeOf(ty_op.operand);
4331 const operand_scalar_ty = operand_ty.scalarType();4291 const operand_scalar_ty = operand_ty.scalarType();
43324292
4333 var dest_ty = self.air.typeOfIndex(inst);4293 const dest_ty = self.air.typeOfIndex(inst);
4334 var dest_scalar_ty = dest_ty.scalarType();4294 const dest_scalar_ty = dest_ty.scalarType();
4295 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
43354296
4336 if (intrinsicsAllowed(operand_scalar_ty, target)) {4297 if (intrinsicsAllowed(operand_scalar_ty, target)) {
4337 // TODO set fast math flag4298 // TODO set fast math flag
4338 const dest_llvm_ty = try self.dg.llvmType(dest_ty);
4339 if (dest_scalar_ty.isSignedInt()) {4299 if (dest_scalar_ty.isSignedInt()) {
4340 return self.builder.buildFPToSI(operand, dest_llvm_ty, "");4300 return self.builder.buildFPToSI(operand, dest_llvm_ty, "");
4341 } else {4301 } else {
...@@ -4343,52 +4303,34 @@ pub const FuncGen = struct {...@@ -4343,52 +4303,34 @@ pub const FuncGen = struct {
4343 }4303 }
4344 }4304 }
43454305
4346 const needs_truncating = blk: {4306 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target)));
4347 const dest_bits = @intCast(u16, dest_scalar_ty.bitSize(target));4307 const libc_ret_ty = self.context.intType(rt_int_bits);
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);
43594308
4360 const operand_bits = operand_scalar_ty.floatBits(target);4309 const operand_bits = operand_scalar_ty.floatBits(target);
4361 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);4310 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
43624311
4363 const dest_bits = @intCast(u16, dest_scalar_ty.bitSize(target));4312 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);
4364 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(dest_bits);4313 const sign_prefix = if (dest_scalar_ty.isSignedInt()) "" else "un";
43654314
4366 var fn_name_buf: [64]u8 = undefined;4315 var fn_name_buf: [64]u8 = undefined;
4367 const fn_name = if (dest_scalar_ty.isSignedInt())4316 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{
4368 std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}f{s}i", .{4317 sign_prefix,
4369 compiler_rt_operand_abbrev,4318 compiler_rt_operand_abbrev,
4370 compiler_rt_dest_abbrev,4319 compiler_rt_dest_abbrev,
4371 }) catch unreachable4320 }) 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;
43774321
4378 const operand_llvm_ty = try self.dg.llvmType(operand_ty);4322 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
4379 const param_types = [1]*const llvm.Type{operand_llvm_ty};4323 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);
4381 const params = [1]*const llvm.Value{operand};4325 const params = [1]*const llvm.Value{operand};
43824326
4383 const result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");4327 const result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
43844328
4385 if (needs_truncating) {4329 if (libc_ret_ty == dest_llvm_ty) {
4386 const requested_ty = self.air.typeOfIndex(inst);4330 return result;
4387 const requested_llvm_ty = try self.dg.llvmType(requested_ty);
4388 return self.builder.buildTrunc(result, requested_llvm_ty, "");
4389 }4331 }
43904332
4391 return result;4333 return self.builder.buildTrunc(result, dest_llvm_ty, "");
4392 }4334 }
43934335
4394 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {4336 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 {...@@ -8448,3 +8390,12 @@ fn needDbgVarWorkaround(dg: *DeclGen, ty: Type) bool {
8448 }8390 }
8449 return false;8391 return false;
8450}8392}
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 {...@@ -476,6 +476,14 @@ pub const Builder = opaque {
476 Name: [*:0]const u8,476 Name: [*:0]const u8,
477 ) *const Value;477 ) *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
479 pub const buildCall = ZigLLVMBuildCall;487 pub const buildCall = ZigLLVMBuildCall;
480 extern fn ZigLLVMBuildCall(488 extern fn ZigLLVMBuildCall(
481 *const Builder,489 *const Builder,