From b63d9745b5d7413acea4f4723ac9f696e3fb8149 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 6 Aug 2023 07:16:39 -0400 Subject: [PATCH] llvm: convert intrinsics to using `Builder` --- src/codegen/llvm.zig | 700 ++++++----------- src/codegen/llvm/Builder.zig | 1376 ++++++++++++++++++++++++--------- src/codegen/llvm/bindings.zig | 126 --- src/zig_llvm.cpp | 347 +-------- src/zig_llvm.h | 82 +- 5 files changed, 1260 insertions(+), 1371 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d9b99ec6d0..48e45400cd 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4962,9 +4962,9 @@ pub const FuncGen = struct { .mul_wrap => try self.airMulWrap(inst), .mul_sat => try self.airMulSat(inst), - .add_safe => try self.airSafeArithmetic(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"), - .sub_safe => try self.airSafeArithmetic(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"), - .mul_safe => try self.airSafeArithmetic(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"), + .add_safe => try self.airSafeArithmetic(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"), + .sub_safe => try self.airSafeArithmetic(inst, .@"ssub.with.overflow", .@"usub.with.overflow"), + .mul_safe => try self.airSafeArithmetic(inst, .@"smul.with.overflow", .@"umul.with.overflow"), .div_float => try self.airDivFloat(inst, false), .div_trunc => try self.airDivTrunc(inst, false), @@ -4989,9 +4989,9 @@ pub const FuncGen = struct { .rem_optimized => try self.airRem(inst, true), .mod_optimized => try self.airMod(inst, true), - .add_with_overflow => try self.airOverflow(inst, "llvm.sadd.with.overflow", "llvm.uadd.with.overflow"), - .sub_with_overflow => try self.airOverflow(inst, "llvm.ssub.with.overflow", "llvm.usub.with.overflow"), - .mul_with_overflow => try self.airOverflow(inst, "llvm.smul.with.overflow", "llvm.umul.with.overflow"), + .add_with_overflow => try self.airOverflow(inst, .@"sadd.with.overflow", .@"uadd.with.overflow"), + .sub_with_overflow => try self.airOverflow(inst, .@"ssub.with.overflow", .@"usub.with.overflow"), + .mul_with_overflow => try self.airOverflow(inst, .@"smul.with.overflow", .@"umul.with.overflow"), .shl_with_overflow => try self.airShlWithOverflow(inst), .bit_and, .bool_and => try self.airAnd(inst), @@ -5100,11 +5100,11 @@ pub const FuncGen = struct { .memcpy => try self.airMemcpy(inst), .set_union_tag => try self.airSetUnionTag(inst), .get_union_tag => try self.airGetUnionTag(inst), - .clz => try self.airClzCtz(inst, .@"llvm.ctlz."), - .ctz => try self.airClzCtz(inst, .@"llvm.cttz."), - .popcount => try self.airBitOp(inst, .@"llvm.ctpop."), + .clz => try self.airClzCtz(inst, .ctlz), + .ctz => try self.airClzCtz(inst, .cttz), + .popcount => try self.airBitOp(inst, .ctpop), .byte_swap => try self.airByteSwap(inst), - .bit_reverse => try self.airBitOp(inst, .@"llvm.bitreverse."), + .bit_reverse => try self.airBitOp(inst, .bitreverse), .tag_name => try self.airTagName(inst), .error_name => try self.airErrorName(inst), .splat => try self.airSplat(inst), @@ -5645,22 +5645,7 @@ pub const FuncGen = struct { const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod)); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); - const llvm_fn_name = "llvm.va_copy"; - const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .ptr }, .normal); - const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse - o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); - - const args: [2]*llvm.Value = .{ dest_list.toLlvm(&self.wip), src_list.toLlvm(&self.wip) }; - _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); - + _ = try self.wip.callIntrinsic(.va_copy, &.{}, &.{ dest_list, src_list }, ""); return if (isByRef(va_list_ty, mod)) dest_list else @@ -5668,25 +5653,10 @@ pub const FuncGen = struct { } fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.dg.object; const un_op = self.air.instructions.items(.data)[inst].un_op; - const list = try self.resolveInst(un_op); + const src_list = try self.resolveInst(un_op); - const llvm_fn_name = "llvm.va_end"; - const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal); - const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse - o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); - - const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; - _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); + _ = try self.wip.callIntrinsic(.va_end, &.{}, &.{src_list}, ""); return .none; } @@ -5697,28 +5667,13 @@ pub const FuncGen = struct { const llvm_va_list_ty = try o.lowerType(va_list_ty); const result_alignment = Builder.Alignment.fromByteUnits(va_list_ty.abiAlignment(mod)); - const list = try self.buildAlloca(llvm_va_list_ty, result_alignment); - - const llvm_fn_name = "llvm.va_start"; - const llvm_fn_ty = try o.builder.fnType(.void, &.{.ptr}, .normal); - const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse - o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); - - const args: [1]*llvm.Value = .{list.toLlvm(&self.wip)}; - _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); + const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); + _ = try self.wip.callIntrinsic(.va_start, &.{}, &.{dest_list}, ""); return if (isByRef(va_list_ty, mod)) - list + dest_list else - try self.wip.load(.normal, llvm_va_list_ty, list, result_alignment, ""); + try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, ""); } fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !Builder.Value { @@ -7570,40 +7525,18 @@ pub const FuncGen = struct { const o = self.dg.object; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const index = pl_op.payload; - const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.size", &.{.i32}); - const args: [1]*llvm.Value = .{ - (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), - }; - return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(.i32, &.{.i32}, .normal)).toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); + return self.wip.callIntrinsic(.@"wasm.memory.size", &.{.i32}, &.{ + try o.builder.intValue(.i32, index), + }, ""); } fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const o = self.dg.object; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const index = pl_op.payload; - const operand = try self.resolveInst(pl_op.operand); - const llvm_fn = try self.getIntrinsic("llvm.wasm.memory.grow", &.{.i32}); - const args: [2]*llvm.Value = .{ - (try o.builder.intConst(.i32, index)).toLlvm(&o.builder), - operand.toLlvm(&self.wip), - }; - return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(.i32, &.{ .i32, .i32 }, .normal)).toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); + return self.wip.callIntrinsic(.@"wasm.memory.grow", &.{.i32}, &.{ + try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), + }, ""); } fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -7636,13 +7569,16 @@ pub const FuncGen = struct { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - const scalar_ty = self.typeOfIndex(inst).scalarType(mod); + const inst_ty = self.typeOfIndex(inst); + const scalar_ty = inst_ty.scalarType(mod); - if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs }); - return self.wip.bin(if (scalar_ty.isSignedInt(mod)) - .@"llvm.smin." - else - .@"llvm.umin.", lhs, rhs, ""); + if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, inst_ty, 2, .{ lhs, rhs }); + return self.wip.callIntrinsic( + if (scalar_ty.isSignedInt(mod)) .smin else .umin, + &.{try o.lowerType(inst_ty)}, + &.{ lhs, rhs }, + "", + ); } fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -7651,13 +7587,16 @@ pub const FuncGen = struct { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - const scalar_ty = self.typeOfIndex(inst).scalarType(mod); + const inst_ty = self.typeOfIndex(inst); + const scalar_ty = inst_ty.scalarType(mod); - if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs }); - return self.wip.bin(if (scalar_ty.isSignedInt(mod)) - .@"llvm.smax." - else - .@"llvm.umax.", lhs, rhs, ""); + if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, inst_ty, 2, .{ lhs, rhs }); + return self.wip.callIntrinsic( + if (scalar_ty.isSignedInt(mod)) .smax else .umax, + &.{try o.lowerType(inst_ty)}, + &.{ lhs, rhs }, + "", + ); } fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -7688,8 +7627,8 @@ pub const FuncGen = struct { fn airSafeArithmetic( fg: *FuncGen, inst: Air.Inst.Index, - signed_intrinsic: []const u8, - unsigned_intrinsic: []const u8, + signed_intrinsic: Builder.Intrinsic, + unsigned_intrinsic: Builder.Intrinsic, ) !Builder.Value { const o = fg.dg.object; const mod = o.module; @@ -7699,36 +7638,19 @@ pub const FuncGen = struct { const rhs = try fg.resolveInst(bin_op.rhs); const inst_ty = fg.typeOfIndex(inst); const scalar_ty = inst_ty.scalarType(mod); - const is_scalar = scalar_ty.ip_index == inst_ty.ip_index; - const intrinsic_name = switch (scalar_ty.isSignedInt(mod)) { - true => signed_intrinsic, - false => unsigned_intrinsic, - }; + const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; const llvm_inst_ty = try o.lowerType(inst_ty); - const llvm_ret_ty = try o.builder.structType(.normal, &.{ - llvm_inst_ty, - try llvm_inst_ty.changeScalar(.i1, &o.builder), - }); - const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_inst_ty, llvm_inst_ty }, .normal); - const llvm_fn = try fg.getIntrinsic(intrinsic_name, &.{llvm_inst_ty}); - const result_struct = (try fg.wip.unimplemented(llvm_ret_ty, "")).finish(fg.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - llvm_fn, - &[_]*llvm.Value{ lhs.toLlvm(&fg.wip), rhs.toLlvm(&fg.wip) }, - 2, - .Fast, - .Auto, - "", - ), &fg.wip); - const overflow_bit = try fg.wip.extractValue(result_struct, &.{1}, ""); - const scalar_overflow_bit = switch (is_scalar) { - true => overflow_bit, - false => (try fg.wip.unimplemented(.i1, "")).finish( + const results = try fg.wip.callIntrinsic(intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); + + const overflow_bit = try fg.wip.extractValue(results, &.{1}, ""); + const scalar_overflow_bit = if (llvm_inst_ty.isVector(&o.builder)) + (try fg.wip.unimplemented(.i1, "")).finish( fg.builder.buildOrReduce(overflow_bit.toLlvm(&fg.wip)), &fg.wip, - ), - }; + ) + else + overflow_bit; const fail_block = try fg.wip.block(1, "OverflowFail"); const ok_block = try fg.wip.block(1, "OverflowOk"); @@ -7738,7 +7660,7 @@ pub const FuncGen = struct { try fg.buildSimplePanic(.integer_overflow); fg.wip.cursor = .{ .block = ok_block }; - return fg.wip.extractValue(result_struct, &.{0}, ""); + return fg.wip.extractValue(results, &.{0}, ""); } fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -7759,10 +7681,12 @@ pub const FuncGen = struct { const scalar_ty = inst_ty.scalarType(mod); if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{}); - return self.wip.bin(if (scalar_ty.isSignedInt(mod)) - .@"llvm.sadd.sat." - else - .@"llvm.uadd.sat.", lhs, rhs, ""); + return self.wip.callIntrinsic( + if (scalar_ty.isSignedInt(mod)) .@"sadd.sat" else .@"uadd.sat", + &.{try o.lowerType(inst_ty)}, + &.{ lhs, rhs }, + "", + ); } fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { @@ -7798,10 +7722,12 @@ pub const FuncGen = struct { const scalar_ty = inst_ty.scalarType(mod); if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{}); - return self.wip.bin(if (scalar_ty.isSignedInt(mod)) - .@"llvm.ssub.sat." - else - .@"llvm.usub.sat.", lhs, rhs, ""); + return self.wip.callIntrinsic( + if (scalar_ty.isSignedInt(mod)) .@"ssub.sat" else .@"usub.sat", + &.{try o.lowerType(inst_ty)}, + &.{ lhs, rhs }, + "", + ); } fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { @@ -7837,10 +7763,12 @@ pub const FuncGen = struct { const scalar_ty = inst_ty.scalarType(mod); if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{}); - return self.wip.bin(if (scalar_ty.isSignedInt(mod)) - .@"llvm.smul.fix.sat." - else - .@"llvm.umul.fix.sat.", lhs, rhs, ""); + return self.wip.callIntrinsic( + if (scalar_ty.isSignedInt(mod)) .@"smul.fix.sat" else .@"umul.fix.sat", + &.{try o.lowerType(inst_ty)}, + &.{ lhs, rhs, try o.builder.intValue(.i32, 0) }, + "", + ); } fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !Builder.Value { @@ -8028,8 +7956,8 @@ pub const FuncGen = struct { fn airOverflow( self: *FuncGen, inst: Air.Inst.Index, - signed_intrinsic: []const u8, - unsigned_intrinsic: []const u8, + signed_intrinsic: Builder.Intrinsic, + unsigned_intrinsic: Builder.Intrinsic, ) !Builder.Value { const o = self.dg.object; const mod = o.module; @@ -8041,48 +7969,29 @@ pub const FuncGen = struct { const lhs_ty = self.typeOf(extra.lhs); const scalar_ty = lhs_ty.scalarType(mod); - const dest_ty = self.typeOfIndex(inst); + const inst_ty = self.typeOfIndex(inst); - const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; - - const llvm_dest_ty = try o.lowerType(dest_ty); + const intrinsic = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; + const llvm_inst_ty = try o.lowerType(inst_ty); const llvm_lhs_ty = try o.lowerType(lhs_ty); + const results = try self.wip.callIntrinsic(intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); - const llvm_fn = try self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); - const llvm_ret_ty = try o.builder.structType( - .normal, - &.{ llvm_lhs_ty, try llvm_lhs_ty.changeScalar(.i1, &o.builder) }, - ); - const llvm_fn_ty = try o.builder.fnType(llvm_ret_ty, &.{ llvm_lhs_ty, llvm_lhs_ty }, .normal); - const result_struct = (try self.wip.unimplemented(llvm_ret_ty, "")).finish( - self.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - llvm_fn, - &[_]*llvm.Value{ lhs.toLlvm(&self.wip), rhs.toLlvm(&self.wip) }, - 2, - .Fast, - .Auto, - "", - ), - &self.wip, - ); + const result_val = try self.wip.extractValue(results, &.{0}, ""); + const overflow_bit = try self.wip.extractValue(results, &.{1}, ""); - const result = try self.wip.extractValue(result_struct, &.{0}, ""); - const overflow_bit = try self.wip.extractValue(result_struct, &.{1}, ""); + const result_index = llvmField(inst_ty, 0, mod).?.index; + const overflow_index = llvmField(inst_ty, 1, mod).?.index; - const result_index = llvmField(dest_ty, 0, mod).?.index; - const overflow_index = llvmField(dest_ty, 1, mod).?.index; - - if (isByRef(dest_ty, mod)) { - const result_alignment = Builder.Alignment.fromByteUnits(dest_ty.abiAlignment(mod)); - const alloca_inst = try self.buildAlloca(llvm_dest_ty, result_alignment); + if (isByRef(inst_ty, mod)) { + const result_alignment = Builder.Alignment.fromByteUnits(inst_ty.abiAlignment(mod)); + const alloca_inst = try self.buildAlloca(llvm_inst_ty, result_alignment); { - const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, result_index, ""); - _ = try self.wip.store(.normal, result, field_ptr, result_alignment); + const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, result_index, ""); + _ = try self.wip.store(.normal, result_val, field_ptr, result_alignment); } { const overflow_alignment = comptime Builder.Alignment.fromByteUnits(1); - const field_ptr = try self.wip.gepStruct(llvm_dest_ty, alloca_inst, overflow_index, ""); + const field_ptr = try self.wip.gepStruct(llvm_inst_ty, alloca_inst, overflow_index, ""); _ = try self.wip.store(.normal, overflow_bit, field_ptr, overflow_alignment); } @@ -8090,9 +7999,9 @@ pub const FuncGen = struct { } var fields: [2]Builder.Value = undefined; - fields[result_index] = result; + fields[result_index] = result_val; fields[overflow_index] = overflow_bit; - return self.wip.buildAggregate(llvm_dest_ty, &fields, ""); + return self.wip.buildAggregate(llvm_inst_ty, &fields, ""); } fn buildElementwiseCall( @@ -8140,22 +8049,7 @@ pub const FuncGen = struct { .function => |function| function, else => unreachable, }; - - const fn_type = try o.builder.fnType(return_type, param_types, .normal); - const f = o.llvm_module.addFunction(fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); - - var global = Builder.Global{ - .type = fn_type, - .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, - }; - var function = Builder.Function{ - .global = @enumFromInt(o.builder.globals.count()), - }; - - try o.builder.llvm.globals.append(self.gpa, f); - _ = try o.builder.addGlobal(fn_name, global); - try o.builder.functions.append(self.gpa, function); - return global.kind.function; + return o.builder.addFunction(try o.builder.fnType(return_type, param_types, .normal), fn_name); } /// Creates a floating point comparison by lowering to the appropriate @@ -8290,22 +8184,22 @@ pub const FuncGen = struct { .mul => return self.wip.bin(.fmul, params[0], params[1], ""), .div => return self.wip.bin(.fdiv, params[0], params[1], ""), .fmod => return self.wip.bin(.frem, params[0], params[1], ""), - .fmax => return self.wip.bin(.@"llvm.maxnum.", params[0], params[1], ""), - .fmin => return self.wip.bin(.@"llvm.minnum.", params[0], params[1], ""), - .ceil => return self.wip.un(.@"llvm.ceil.", params[0], ""), - .cos => return self.wip.un(.@"llvm.cos.", params[0], ""), - .exp => return self.wip.un(.@"llvm.exp.", params[0], ""), - .exp2 => return self.wip.un(.@"llvm.exp2.", params[0], ""), - .fabs => return self.wip.un(.@"llvm.fabs.", params[0], ""), - .floor => return self.wip.un(.@"llvm.floor.", params[0], ""), - .log => return self.wip.un(.@"llvm.log.", params[0], ""), - .log10 => return self.wip.un(.@"llvm.log10.", params[0], ""), - .log2 => return self.wip.un(.@"llvm.log2.", params[0], ""), - .round => return self.wip.un(.@"llvm.round.", params[0], ""), - .sin => return self.wip.un(.@"llvm.sin.", params[0], ""), - .sqrt => return self.wip.un(.@"llvm.sqrt.", params[0], ""), - .trunc => return self.wip.un(.@"llvm.trunc.", params[0], ""), - .fma => return self.wip.fusedMultiplyAdd(params[0], params[1], params[2]), + .fmax => return self.wip.callIntrinsic(.maxnum, &.{llvm_ty}, ¶ms, ""), + .fmin => return self.wip.callIntrinsic(.minnum, &.{llvm_ty}, ¶ms, ""), + .ceil => return self.wip.callIntrinsic(.ceil, &.{llvm_ty}, ¶ms, ""), + .cos => return self.wip.callIntrinsic(.cos, &.{llvm_ty}, ¶ms, ""), + .exp => return self.wip.callIntrinsic(.exp, &.{llvm_ty}, ¶ms, ""), + .exp2 => return self.wip.callIntrinsic(.exp2, &.{llvm_ty}, ¶ms, ""), + .fabs => return self.wip.callIntrinsic(.fabs, &.{llvm_ty}, ¶ms, ""), + .floor => return self.wip.callIntrinsic(.floor, &.{llvm_ty}, ¶ms, ""), + .log => return self.wip.callIntrinsic(.log, &.{llvm_ty}, ¶ms, ""), + .log10 => return self.wip.callIntrinsic(.log10, &.{llvm_ty}, ¶ms, ""), + .log2 => return self.wip.callIntrinsic(.log2, &.{llvm_ty}, ¶ms, ""), + .round => return self.wip.callIntrinsic(.round, &.{llvm_ty}, ¶ms, ""), + .sin => return self.wip.callIntrinsic(.sin, &.{llvm_ty}, ¶ms, ""), + .sqrt => return self.wip.callIntrinsic(.sqrt, &.{llvm_ty}, ¶ms, ""), + .trunc => return self.wip.callIntrinsic(.trunc, &.{llvm_ty}, ¶ms, ""), + .fma => return self.wip.callIntrinsic(.fma, &.{llvm_ty}, ¶ms, ""), .tan => unreachable, }; @@ -8499,25 +8393,27 @@ pub const FuncGen = struct { const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); - const result = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(mod)) - .@"llvm.sshl.sat." - else - .@"llvm.ushl.sat.", lhs, casted_rhs, ""); + const llvm_lhs_ty = try o.lowerType(lhs_ty); + const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); + const result = try self.wip.callIntrinsic( + if (lhs_scalar_ty.isSignedInt(mod)) .@"sshl.sat" else .@"ushl.sat", + &.{llvm_lhs_ty}, + &.{ lhs, casted_rhs }, + "", + ); // LLVM langref says "If b is (statically or dynamically) equal to or // larger than the integer bit width of the arguments, the result is a // poison value." // However Zig semantics says that saturating shift left can never produce // undefined; instead it saturates. - const lhs_llvm_ty = try o.lowerType(lhs_ty); - const lhs_scalar_llvm_ty = lhs_llvm_ty.scalarType(&o.builder); const bits = try o.builder.splatValue( - lhs_llvm_ty, - try o.builder.intConst(lhs_scalar_llvm_ty, lhs_bits), + llvm_lhs_ty, + try o.builder.intConst(llvm_lhs_scalar_ty, lhs_bits), ); const lhs_max = try o.builder.splatValue( - lhs_llvm_ty, - try o.builder.intConst(lhs_scalar_llvm_ty, -1), + llvm_lhs_ty, + try o.builder.intConst(llvm_lhs_scalar_ty, -1), ); const in_range = try self.wip.icmp(.ult, rhs, bits, ""); return self.wip.select(in_range, result, lhs_max, ""); @@ -8940,90 +8836,38 @@ pub const FuncGen = struct { fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { _ = inst; - const o = self.dg.object; - const llvm_fn = try self.getIntrinsic("llvm.trap", &.{}); - _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), - llvm_fn, - undefined, - 0, - .Cold, - .Auto, - "", - ), &self.wip); + _ = try self.wip.callIntrinsic(.trap, &.{}, &.{}, ""); _ = try self.wip.@"unreachable"(); return .none; } fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { _ = inst; - const o = self.dg.object; - const llvm_fn = try self.getIntrinsic("llvm.debugtrap", &.{}); - _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(.void, &.{}, .normal)).toLlvm(&o.builder), - llvm_fn, - undefined, - 0, - .C, - .Auto, - "", - ), &self.wip); + _ = try self.wip.callIntrinsic(.debugtrap, &.{}, &.{}, ""); return .none; } fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { _ = inst; const o = self.dg.object; - const mod = o.module; const llvm_usize = try o.lowerType(Type.usize); - const target = mod.getTarget(); - if (!target_util.supportsReturnAddress(target)) { + if (!target_util.supportsReturnAddress(o.module.getTarget())) { // https://github.com/ziglang/zig/issues/11946 return o.builder.intValue(llvm_usize, 0); } - - const llvm_fn = try self.getIntrinsic("llvm.returnaddress", &.{}); - const params = [_]*llvm.Value{ - (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), - }; - const ptr_val = (try self.wip.unimplemented(.ptr, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(.ptr, &.{.i32}, .normal)).toLlvm(&o.builder), - llvm_fn, - ¶ms, - params.len, - .Fast, - .Auto, - "", - ), &self.wip); - return self.wip.cast(.ptrtoint, ptr_val, llvm_usize, ""); + const result = try self.wip.callIntrinsic(.returnaddress, &.{}, &.{ + try o.builder.intValue(.i32, 0), + }, ""); + return self.wip.cast(.ptrtoint, result, llvm_usize, ""); } fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { _ = inst; const o = self.dg.object; - const llvm_fn_name = "llvm.frameaddress.p0"; - const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { - const fn_type = try o.builder.fnType(.ptr, &.{.i32}, .normal); - break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type.toLlvm(&o.builder)); - }; - const llvm_fn_ty = try o.builder.fnType(.ptr, &.{.i32}, .normal); - - const params = [_]*llvm.Value{ - (try o.builder.intConst(.i32, 0)).toLlvm(&o.builder), - }; - const ptr_val = (try self.wip.unimplemented(llvm_fn_ty.functionReturn(&o.builder), "")).finish( - self.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - llvm_fn, - ¶ms, - params.len, - .Fast, - .Auto, - "", - ), - &self.wip, - ); - return self.wip.cast(.ptrtoint, ptr_val, try o.lowerType(Type.usize), ""); + const result = try self.wip.callIntrinsic(.frameaddress, &.{.ptr}, &.{ + try o.builder.intValue(.i32, 0), + }, ""); + return self.wip.cast(.ptrtoint, result, try o.lowerType(Type.usize), ""); } fn airFence(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -9526,26 +9370,37 @@ pub const FuncGen = struct { return self.buildFloatOp(.neg, operand_ty, 1, .{operand}); } - fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value { + fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { const o = self.dg.object; const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const inst_ty = self.typeOfIndex(inst); + const operand_ty = self.typeOf(ty_op.operand); const operand = try self.resolveInst(ty_op.operand); - const wrong_size_result = try self.wip.bin(intrinsic, operand, (try o.builder.intConst(.i1, 0)).toValue(), ""); - - const result_ty = self.typeOfIndex(inst); - return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); + const result = + try self.wip.callIntrinsic( + intrinsic, + &.{try o.lowerType(operand_ty)}, + &.{ operand, .false }, + "", + ); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); } - fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Function.Instruction.Tag) !Builder.Value { + fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { const o = self.dg.object; const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const inst_ty = self.typeOfIndex(inst); + const operand_ty = self.typeOf(ty_op.operand); const operand = try self.resolveInst(ty_op.operand); - const wrong_size_result = try self.wip.un(intrinsic, operand, ""); - - const result_ty = self.typeOfIndex(inst); - return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); + const result = try self.wip.callIntrinsic( + intrinsic, + &.{try o.lowerType(operand_ty)}, + &.{operand}, + "", + ); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); } fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -9556,6 +9411,7 @@ pub const FuncGen = struct { var bits = operand_ty.intInfo(mod).bits; assert(bits % 8 == 0); + const inst_ty = self.typeOfIndex(inst); var operand = try self.resolveInst(ty_op.operand); var llvm_operand_ty = try o.lowerType(operand_ty); @@ -9576,10 +9432,8 @@ pub const FuncGen = struct { bits = bits + 8; } - const wrong_size_result = try self.wip.un(.@"llvm.bswap.", operand, ""); - - const result_ty = self.typeOfIndex(inst); - return self.wip.conv(.unsigned, wrong_size_result, try o.lowerType(result_ty), ""); + const result = try self.wip.callIntrinsic(.bswap, &.{llvm_operand_ty}, &.{operand}, ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); } fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -9609,11 +9463,7 @@ pub const FuncGen = struct { self.wip.cursor = .{ .block = end_block }; const phi = try self.wip.phi(.i1, ""); - try phi.finish( - &.{ Builder.Constant.true.toValue(), Builder.Constant.false.toValue() }, - &.{ valid_block, invalid_block }, - &self.wip, - ); + try phi.finish(&.{ .true, .false }, &.{ valid_block, invalid_block }, &self.wip); return phi.toValue(); } @@ -9646,37 +9496,24 @@ pub const FuncGen = struct { errdefer assert(o.named_enum_map.remove(enum_type.decl)); const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); - const llvm_fn_name = try o.builder.fmt("__zig_is_named_enum_value_{}", .{ - fqn.fmt(&mod.intern_pool), - }); + const function_index = try o.builder.addFunction( + try o.builder.fnType(.i1, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal), + try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}), + ); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - const fn_type = try o.builder.fnType(.i1, &.{ - try o.lowerType(enum_type.tag_ty.toType()), - }, .normal); - const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); - fn_val.setLinkage(.Internal); - fn_val.setFunctionCallConv(.Fast); - try o.addCommonFnAttributes(&attributes, fn_val); + function_index.toLlvm(&o.builder).setLinkage(.Internal); + function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); + try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); - var global = Builder.Global{ - .linkage = .internal, - .type = fn_type, - .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, - }; - var function = Builder.Function{ - .global = @enumFromInt(o.builder.globals.count()), - .call_conv = .fastcc, - .attributes = try attributes.finish(&o.builder), - }; - try o.builder.llvm.globals.append(self.gpa, fn_val); - _ = try o.builder.addGlobal(llvm_fn_name, global); - try o.builder.functions.append(self.gpa, function); - gop.value_ptr.* = global.kind.function; + function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; + function_index.ptr(&o.builder).call_conv = .fastcc; + function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); + gop.value_ptr.* = function_index; - var wip = try Builder.WipFunction.init(&o.builder, global.kind.function); + var wip = try Builder.WipFunction.init(&o.builder, function_index); defer wip.deinit(); wip.cursor = .{ .block = try wip.block(0, "Entry") }; @@ -9693,13 +9530,13 @@ pub const FuncGen = struct { try wip_switch.addCase(this_tag_int_value, named_block, &wip); } wip.cursor = .{ .block = named_block }; - _ = try wip.ret(Builder.Constant.true.toValue()); + _ = try wip.ret(.true); wip.cursor = .{ .block = unnamed_block }; - _ = try wip.ret(Builder.Constant.false.toValue()); + _ = try wip.ret(.false); try wip.finish(); - return global.kind.function; + return function_index; } fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -9730,38 +9567,27 @@ pub const FuncGen = struct { if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; errdefer assert(o.decl_map.remove(enum_type.decl)); + const usize_ty = try o.lowerType(Type.usize); + const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); - const llvm_fn_name = try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); + const function_index = try o.builder.addFunction( + try o.builder.fnType(ret_ty, &.{try o.lowerType(enum_type.tag_ty.toType())}, .normal), + try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}), + ); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0); - const usize_ty = try o.lowerType(Type.usize); + function_index.toLlvm(&o.builder).setLinkage(.Internal); + function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); + try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); - const fn_type = try o.builder.fnType(ret_ty, &.{ - try o.lowerType(enum_type.tag_ty.toType()), - }, .normal); - const fn_val = o.llvm_module.addFunction(llvm_fn_name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); - fn_val.setLinkage(.Internal); - fn_val.setFunctionCallConv(.Fast); - try o.addCommonFnAttributes(&attributes, fn_val); + function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; + function_index.ptr(&o.builder).call_conv = .fastcc; + function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); + gop.value_ptr.* = function_index.ptrConst(&o.builder).global; - var global = Builder.Global{ - .linkage = .internal, - .type = fn_type, - .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, - }; - var function = Builder.Function{ - .global = @enumFromInt(o.builder.globals.count()), - .call_conv = .fastcc, - .attributes = try attributes.finish(&o.builder), - }; - try o.builder.llvm.globals.append(self.gpa, fn_val); - gop.value_ptr.* = try o.builder.addGlobal(llvm_fn_name, global); - try o.builder.functions.append(self.gpa, function); - - var wip = try Builder.WipFunction.init(&o.builder, global.kind.function); + var wip = try Builder.WipFunction.init(&o.builder, function_index); defer wip.deinit(); wip.cursor = .{ .block = try wip.block(0, "Entry") }; @@ -9817,7 +9643,7 @@ pub const FuncGen = struct { _ = try wip.@"unreachable"(); try wip.finish(); - return global.kind.function; + return function_index; } fn getCmpLtErrorsLenFunction(self: *FuncGen) !Builder.Function.Index { @@ -9826,33 +9652,23 @@ pub const FuncGen = struct { const name = try o.builder.string(lt_errors_fn_name); if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; - // Function signature: fn (anyerror) bool - - const fn_type = try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal); - const llvm_fn = o.llvm_module.addFunction(name.slice(&o.builder).?, fn_type.toLlvm(&o.builder)); + const function_index = try o.builder.addFunction( + try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal), + name, + ); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); - llvm_fn.setLinkage(.Internal); - llvm_fn.setFunctionCallConv(.Fast); - try o.addCommonFnAttributes(&attributes, llvm_fn); + function_index.toLlvm(&o.builder).setLinkage(.Internal); + function_index.toLlvm(&o.builder).setFunctionCallConv(.Fast); + try o.addCommonFnAttributes(&attributes, function_index.toLlvm(&o.builder)); - var global = Builder.Global{ - .linkage = .internal, - .type = fn_type, - .kind = .{ .function = @enumFromInt(o.builder.functions.items.len) }, - }; - var function = Builder.Function{ - .global = @enumFromInt(o.builder.globals.count()), - .call_conv = .fastcc, - .attributes = try attributes.finish(&o.builder), - }; + function_index.ptrConst(&o.builder).global.ptr(&o.builder).linkage = .internal; + function_index.ptr(&o.builder).call_conv = .fastcc; + function_index.ptr(&o.builder).attributes = try attributes.finish(&o.builder); - try o.builder.llvm.globals.append(self.gpa, llvm_fn); - _ = try o.builder.addGlobal(name, global); - try o.builder.functions.append(self.gpa, function); - return global.kind.function; + return function_index; } fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -10416,29 +10232,12 @@ pub const FuncGen = struct { .data => {}, } - const llvm_fn_name = "llvm.prefetch.p0"; - // declare void @llvm.prefetch(i8*, i32, i32, i32) - const llvm_fn_ty = try o.builder.fnType(.void, &.{ .ptr, .i32, .i32, .i32 }, .normal); - const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse - o.llvm_module.addFunction(llvm_fn_name, llvm_fn_ty.toLlvm(&o.builder)); - - const ptr = try self.resolveInst(prefetch.ptr); - - const params = [_]*llvm.Value{ - ptr.toLlvm(&self.wip), - (try o.builder.intConst(.i32, @intFromEnum(prefetch.rw))).toLlvm(&o.builder), - (try o.builder.intConst(.i32, prefetch.locality)).toLlvm(&o.builder), - (try o.builder.intConst(.i32, @intFromEnum(prefetch.cache))).toLlvm(&o.builder), - }; - _ = (try self.wip.unimplemented(.void, "")).finish(self.builder.buildCallOld( - llvm_fn_ty.toLlvm(&o.builder), - fn_val, - ¶ms, - params.len, - .C, - .Auto, - "", - ), &self.wip); + _ = try self.wip.callIntrinsic(.prefetch, &.{.ptr}, &.{ + try self.resolveInst(prefetch.ptr), + try o.builder.intValue(.i32, prefetch.rw), + try o.builder.intValue(.i32, prefetch.locality), + try o.builder.intValue(.i32, prefetch.cache), + }, ""); return .none; } @@ -10451,26 +10250,20 @@ pub const FuncGen = struct { return self.wip.cast(.addrspacecast, operand, try o.lowerType(inst_ty), ""); } - fn amdgcnWorkIntrinsic(self: *FuncGen, dimension: u32, default: u32, comptime basename: []const u8) !Builder.Value { + fn amdgcnWorkIntrinsic( + self: *FuncGen, + dimension: u32, + default: u32, + comptime basename: []const u8, + ) !Builder.Value { const o = self.dg.object; - const llvm_fn_name = switch (dimension) { - 0 => basename ++ ".x", - 1 => basename ++ ".y", - 2 => basename ++ ".z", + const intrinsic = switch (dimension) { + 0 => @field(Builder.Intrinsic, basename ++ ".x"), + 1 => @field(Builder.Intrinsic, basename ++ ".y"), + 2 => @field(Builder.Intrinsic, basename ++ ".z"), else => return o.builder.intValue(.i32, default), }; - - const args: [0]*llvm.Value = .{}; - const llvm_fn = try self.getIntrinsic(llvm_fn_name, &.{}); - return (try self.wip.unimplemented(.i32, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(.i32, &.{}, .normal)).toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); + return self.wip.callIntrinsic(intrinsic, &.{}, &.{}, ""); } fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -10480,7 +10273,7 @@ pub const FuncGen = struct { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const dimension = pl_op.payload; - return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workitem.id"); + return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workitem.id"); } fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -10492,27 +10285,9 @@ pub const FuncGen = struct { const dimension = pl_op.payload; if (dimension >= 3) return o.builder.intValue(.i32, 1); - var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(&o.builder); - // Fetch the dispatch pointer, which points to this structure: // https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/adae6c61e10d371f7cbc3d0e94ae2c070cab18a4/src/inc/hsa.h#L2913 - const llvm_fn = try self.getIntrinsic("llvm.amdgcn.dispatch.ptr", &.{}); - const args: [0]*llvm.Value = .{}; - const llvm_ret_ty = try o.builder.ptrType(Builder.AddrSpace.amdgpu.constant); - const dispatch_ptr = (try self.wip.unimplemented(llvm_ret_ty, "")).finish(self.builder.buildCallOld( - (try o.builder.fnType(llvm_ret_ty, &.{}, .normal)).toLlvm(&o.builder), - llvm_fn, - &args, - args.len, - .Fast, - .Auto, - "", - ), &self.wip); - try attributes.addRetAttr(.{ - .@"align" = comptime Builder.Alignment.fromByteUnits(4), - }, &o.builder); - o.addAttrInt(dispatch_ptr.toLlvm(&self.wip), 0, "align", 4); + const dispatch_ptr = try self.wip.callIntrinsic(.@"amdgcn.dispatch.ptr", &.{}, &.{}, ""); // Load the work_group_* member from the struct as u16. // Just treat the dispatch pointer as an array of u16 to keep things simple. @@ -10530,7 +10305,7 @@ pub const FuncGen = struct { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const dimension = pl_op.payload; - return self.amdgcnWorkIntrinsic(dimension, 0, "llvm.amdgcn.workgroup.id"); + return self.amdgcnWorkIntrinsic(dimension, 0, "amdgcn.workgroup.id"); } fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index { @@ -10716,20 +10491,6 @@ pub const FuncGen = struct { } } - fn getIntrinsic( - fg: *FuncGen, - name: []const u8, - types: []const Builder.Type, - ) Allocator.Error!*llvm.Value { - const o = fg.dg.object; - const id = llvm.lookupIntrinsicID(name.ptr, name.len); - assert(id != 0); - const llvm_types = try o.gpa.alloc(*llvm.Type, types.len); - defer o.gpa.free(llvm_types); - for (llvm_types, types) |*llvm_type, ty| llvm_type.* = ty.toLlvm(&o.builder); - return o.llvm_module.getIntrinsicDeclaration(id, llvm_types.ptr, llvm_types.len); - } - /// Load a by-ref type by constructing a new alloca and performing a memcpy. fn loadByRef( fg: *FuncGen, @@ -10778,7 +10539,7 @@ pub const FuncGen = struct { assert(info.flags.vector_index != .runtime); if (info.flags.vector_index != .none) { - const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index)); + const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); const vec_elem_ty = try o.lowerType(elem_ty); const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); @@ -10848,7 +10609,7 @@ pub const FuncGen = struct { assert(info.flags.vector_index != .runtime); if (info.flags.vector_index != .none) { - const index_u32 = try o.builder.intValue(.i32, @intFromEnum(info.flags.vector_index)); + const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); const vec_elem_ty = try o.lowerType(elem_ty); const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); @@ -10982,26 +10743,15 @@ pub const FuncGen = struct { else => unreachable, }; - const fn_llvm_ty = (try o.builder.fnType(llvm_usize, &(.{llvm_usize} ** 2), .normal)).toLlvm(&o.builder); - const array_ptr_as_usize = try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""); - const args = [_]*llvm.Value{ array_ptr_as_usize.toLlvm(&fg.wip), default_value.toLlvm(&fg.wip) }; - const asm_fn = llvm.getInlineAsm( - fn_llvm_ty, - arch_specific.template.ptr, - arch_specific.template.len, - arch_specific.constraints.ptr, - arch_specific.constraints.len, - .True, // has side effects - .False, // alignstack - .ATT, - .False, // can throw + return try fg.wip.callAsm( + .none, + try o.builder.fnType(llvm_usize, &.{ llvm_usize, llvm_usize }, .normal), + .{ .sideeffect = true }, + try o.builder.string(arch_specific.template), + try o.builder.string(arch_specific.constraints), + &.{ try fg.wip.cast(.ptrtoint, array_ptr, llvm_usize, ""), default_value }, + "", ); - - const call = (try fg.wip.unimplemented(llvm_usize, "")).finish( - fg.builder.buildCallOld(fn_llvm_ty, asm_fn, &args, args.len, .C, .Auto, ""), - &fg.wip, - ); - return call; } fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type { diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 95c1218b70..28545fe95e 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -50,10 +50,12 @@ constant_extra: std.ArrayListUnmanaged(u32), constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb), pub const expected_args_len = 16; +pub const expected_attrs_len = 16; pub const expected_fields_len = 32; pub const expected_gep_indices_len = 8; pub const expected_cases_len = 8; pub const expected_incoming_len = 8; +pub const expected_intrinsic_name_len = 64; pub const Options = struct { allocator: Allocator, @@ -151,11 +153,14 @@ pub const Type = enum(u32) { i80, i128, ptr, + @"ptr addrspace(4)", none = std.math.maxInt(u32), _, pub const err_int = Type.i16; + pub const ptr_amdgpu_constant = + @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant})); pub const Tag = enum(u4) { simple, @@ -391,7 +396,7 @@ pub const Type = enum(u32) { .double, .i64, .x86_mmx => 64, .x86_fp80, .i80 => 80, .fp128, .ppc_fp128, .i128 => 128, - .ptr => @panic("TODO: query data layout"), + .ptr, .@"ptr addrspace(4)" => @panic("TODO: query data layout"), _ => { const item = builder.type_items.items[@intFromEnum(self)]; return switch (item.tag) { @@ -690,7 +695,7 @@ pub const Type = enum(u32) { } }, .integer => try writer.print("i{d}", .{item.data}), - .pointer => try writer.print("ptr{}", .{@as(AddrSpace, @enumFromInt(item.data))}), + .pointer => try writer.print("ptr{ }", .{@as(AddrSpace, @enumFromInt(item.data))}), .target => { var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); const types = extra.trail.next(extra.data.types_len, Type, data.builder); @@ -795,6 +800,7 @@ pub const Type = enum(u32) { .i80, .i128, .ptr, + .@"ptr addrspace(4)", => true, .none => unreachable, _ => { @@ -1201,12 +1207,20 @@ pub const Attribute = union(Kind) { try writer.print(",{d}", .{allocsize.num_elems}); try writer.writeByte(')'); }, - .memory => |memory| try writer.print(" {s}({s}, argmem: {s}, inaccessiblemem: {s})", .{ - @tagName(attribute), - @tagName(memory.other), - @tagName(memory.argmem), - @tagName(memory.inaccessiblemem), - }), + .memory => |memory| { + try writer.print(" {s}(", .{@tagName(attribute)}); + var any = memory.other != .none or + (memory.argmem == .none and memory.inaccessiblemem == .none); + if (any) try writer.writeAll(@tagName(memory.other)); + inline for (.{ "argmem", "inaccessiblemem" }) |kind| { + if (@field(memory, kind) != memory.other) { + if (any) try writer.writeAll(", "); + try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) }); + any = true; + } + } + try writer.writeByte(')'); + }, .uwtable => |uwtable| if (uwtable != .none) { try writer.print(" {s}", .{@tagName(attribute)}); if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)}); @@ -1424,12 +1438,16 @@ pub const Attribute = union(Kind) { }; pub const Memory = packed struct(u32) { - argmem: Effect, - inaccessiblemem: Effect, - other: Effect, + argmem: Effect = .none, + inaccessiblemem: Effect = .none, + other: Effect = .none, _: u26 = 0, pub const Effect = enum(u2) { none, read, write, readwrite }; + + fn all(effect: Effect) Memory { + return .{ .argmem = effect, .inaccessiblemem = effect, .other = effect }; + } }; pub const UwTable = enum(u32) { @@ -2279,6 +2297,820 @@ pub const Variable = struct { }; }; +pub const Intrinsic = enum { + // Variable Argument Handling + va_start, + va_end, + va_copy, + + // Code Generator + returnaddress, + addressofreturnaddress, + sponentry, + frameaddress, + prefetch, + @"thread.pointer", + + // Standard C/C++ Library + abs, + smax, + smin, + umax, + umin, + memcpy, + @"memcpy.inline", + memmove, + memset, + @"memset.inline", + sqrt, + powi, + sin, + cos, + pow, + exp, + exp2, + ldexp, + frexp, + log, + log10, + log2, + fma, + fabs, + minnum, + maxnum, + minimum, + maximum, + copysign, + floor, + ceil, + trunc, + rint, + nearbyint, + round, + roundeven, + lround, + llround, + lrint, + llrint, + + // Bit Manipulation + bitreverse, + bswap, + ctpop, + ctlz, + cttz, + fshl, + fshr, + + // Arithmetic with Overflow + @"sadd.with.overflow", + @"uadd.with.overflow", + @"ssub.with.overflow", + @"usub.with.overflow", + @"smul.with.overflow", + @"umul.with.overflow", + + // Saturation Arithmetic + @"sadd.sat", + @"uadd.sat", + @"ssub.sat", + @"usub.sat", + @"sshl.sat", + @"ushl.sat", + + // Fixed Point Arithmetic + @"smul.fix", + @"umul.fix", + @"smul.fix.sat", + @"umul.fix.sat", + @"sdiv.fix", + @"udiv.fix", + @"sdiv.fix.sat", + @"udiv.fix.sat", + + // Specialised Arithmetic + canonicalisze, + fmuladd, + + // Vector Reduction + @"vector.reduce.add", + @"vector.reduce.fadd", + @"vector.reduce.mul", + @"vector.reduce.fmul", + @"vector.reduce.and", + @"vector.reduce.or", + @"vector.reduce.xor", + @"vector.reduce.smax", + @"vector.reduce.smin", + @"vector.reduce.umax", + @"vector.reduce.umin", + @"vector.reduce.fmax", + @"vector.reduce.fmin", + @"vector.reduce.fmaximum", + @"vector.reduce.fminimum", + @"vector.reduce.insert", + @"vector.reduce.extract", + @"vector.insert", + @"vector.extract", + + // General + @"llvm.var.annotation", + @"llvm.ptr.annotation", + annotation, + @"codeview.annotation", + trap, + debugtrap, + ubsantrap, + stackprotector, + stackguard, + objectsize, + expect, + @"expect.with.probability", + assume, + @"ssa.copy", + @"type.test", + @"type.checked.load", + @"type.checked.load.relative", + @"arithmetic.fence", + donothing, + @"load.relative", + @"llvm.sideeffect", + @"is.constant", + ptrmask, + @"threadlocal.address", + vscale, + + // AMDGPU + @"amdgcn.workitem.id.x", + @"amdgcn.workitem.id.y", + @"amdgcn.workitem.id.z", + @"amdgcn.workgroup.id.x", + @"amdgcn.workgroup.id.y", + @"amdgcn.workgroup.id.z", + @"amdgcn.dispatch.ptr", + + // WebAssembly + @"wasm.memory.size", + @"wasm.memory.grow", + + const Signature = struct { + params: []const Parameter = &.{}, + attrs: []const Attribute = &.{}, + + const Parameter = struct { + kind: Kind, + attrs: []const Attribute = &.{}, + + const Kind = union(enum) { + type: Type, + overloaded, + overloaded_tuple: u8, + matches: u8, + matches_tuple: packed struct { param: u4, field: u4 }, + matches_with_overflow: u8, + }; + }; + }; + + const signatures = std.enums.EnumArray(Intrinsic, Signature).initDefault(.{}, .{ + .va_start = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + .{ .kind = .{ .type = .ptr } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, + }, + .va_end = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + .{ .kind = .{ .type = .ptr } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, + }, + .va_copy = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + .{ .kind = .{ .type = .ptr } }, + .{ .kind = .{ .type = .ptr } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, + }, + + .returnaddress = .{ + .params = &.{ + .{ .kind = .{ .type = .ptr } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .addressofreturnaddress = .{ + .params = &.{ + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .sponentry = .{ + .params = &.{ + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .frameaddress = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .prefetch = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + .{ .kind = .overloaded, .attrs = &.{ .nocapture, .readonly } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.readwrite) } }, + }, + .@"thread.pointer" = .{ + .params = &.{ + .{ .kind = .{ .type = .ptr } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .abs = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .smax = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .smin = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .umax = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .umin = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .sqrt = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .powi = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .sin = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .cos = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .pow = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .exp = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .exp2 = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .ldexp = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .frexp = .{ + .params = &.{ + .{ .kind = .{ .overloaded_tuple = 2 } }, + .{ .kind = .{ .matches_tuple = .{ .param = 0, .field = 0 } } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .log = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .log10 = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .log2 = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .fma = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .fabs = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .minnum = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .maxnum = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .minimum = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .maximum = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .copysign = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .floor = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .ceil = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .trunc = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .rint = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .nearbyint = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .round = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .roundeven = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .lround = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .llround = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .lrint = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .llrint = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .overloaded }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .bitreverse = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .bswap = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .ctpop = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .ctlz = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .cttz = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .fshl = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .fshr = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .@"sadd.with.overflow" = .{ + .params = &.{ + .{ .kind = .{ .matches_with_overflow = 1 } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"uadd.with.overflow" = .{ + .params = &.{ + .{ .kind = .{ .matches_with_overflow = 1 } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"ssub.with.overflow" = .{ + .params = &.{ + .{ .kind = .{ .matches_with_overflow = 1 } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"usub.with.overflow" = .{ + .params = &.{ + .{ .kind = .{ .matches_with_overflow = 1 } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"smul.with.overflow" = .{ + .params = &.{ + .{ .kind = .{ .matches_with_overflow = 1 } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"umul.with.overflow" = .{ + .params = &.{ + .{ .kind = .{ .matches_with_overflow = 1 } }, + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 1 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .@"sadd.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"uadd.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"ssub.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"usub.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"sshl.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"ushl.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .@"smul.fix" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"umul.fix" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"smul.fix.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"umul.fix.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"sdiv.fix" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"udiv.fix" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"sdiv.fix.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"udiv.fix.sat" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .matches = 0 } }, + .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .trap = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + }, + .attrs = &.{ .cold, .noreturn, .nounwind, .{ .memory = .{ .inaccessiblemem = .write } } }, + }, + .debugtrap = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + }, + .attrs = &.{.nounwind}, + }, + .ubsantrap = .{ + .params = &.{ + .{ .kind = .{ .type = .void } }, + .{ .kind = .{ .type = .i8 }, .attrs = &.{.immarg} }, + }, + .attrs = &.{ .cold, .noreturn, .nounwind }, + }, + + .@"amdgcn.workitem.id.x" = .{ + .params = &.{ + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"amdgcn.workitem.id.y" = .{ + .params = &.{ + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"amdgcn.workitem.id.z" = .{ + .params = &.{ + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"amdgcn.workgroup.id.x" = .{ + .params = &.{ + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"amdgcn.workgroup.id.y" = .{ + .params = &.{ + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"amdgcn.workgroup.id.z" = .{ + .params = &.{ + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"amdgcn.dispatch.ptr" = .{ + .params = &.{ + .{ + .kind = .{ .type = Type.ptr_amdgpu_constant }, + .attrs = &.{.{ .@"align" = Builder.Alignment.fromByteUnits(4) }}, + }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + + .@"wasm.memory.size" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .type = .i32 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, + }, + .@"wasm.memory.grow" = .{ + .params = &.{ + .{ .kind = .overloaded }, + .{ .kind = .{ .type = .i32 } }, + .{ .kind = .{ .matches = 0 } }, + }, + .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .willreturn }, + }, + }); +}; + pub const Function = struct { global: Global.Index, call_conv: CallConv = CallConv.default, @@ -2414,39 +3246,6 @@ pub const Function = struct { insertelement, insertvalue, inttoptr, - @"llvm.maxnum.", - @"llvm.minnum.", - @"llvm.ceil.", - @"llvm.cos.", - @"llvm.exp.", - @"llvm.exp2.", - @"llvm.fabs.", - @"llvm.floor.", - @"llvm.log.", - @"llvm.log10.", - @"llvm.log2.", - @"llvm.round.", - @"llvm.sin.", - @"llvm.sqrt.", - @"llvm.trunc.", - @"llvm.fma.", - @"llvm.bitreverse.", - @"llvm.bswap.", - @"llvm.ctpop.", - @"llvm.ctlz.", - @"llvm.cttz.", - @"llvm.sadd.sat.", - @"llvm.smax.", - @"llvm.smin.", - @"llvm.smul.fix.sat.", - @"llvm.sshl.sat.", - @"llvm.ssub.sat.", - @"llvm.uadd.sat.", - @"llvm.umax.", - @"llvm.umin.", - @"llvm.umul.fix.sat.", - @"llvm.ushl.sat.", - @"llvm.usub.sat.", load, @"load atomic", @"load atomic volatile", @@ -2575,22 +3374,6 @@ pub const Function = struct { .@"frem fast", .fsub, .@"fsub fast", - .@"llvm.maxnum.", - .@"llvm.minnum.", - .@"llvm.ctlz.", - .@"llvm.cttz.", - .@"llvm.sadd.sat.", - .@"llvm.smax.", - .@"llvm.smin.", - .@"llvm.smul.fix.sat.", - .@"llvm.sshl.sat.", - .@"llvm.ssub.sat.", - .@"llvm.uadd.sat.", - .@"llvm.umax.", - .@"llvm.umin.", - .@"llvm.umul.fix.sat.", - .@"llvm.ushl.sat.", - .@"llvm.usub.sat.", .lshr, .@"lshr exact", .mul, @@ -2710,22 +3493,6 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, wip.builder), .fneg, .@"fneg fast", - .@"llvm.ceil.", - .@"llvm.cos.", - .@"llvm.exp.", - .@"llvm.exp2.", - .@"llvm.fabs.", - .@"llvm.floor.", - .@"llvm.log.", - .@"llvm.log10.", - .@"llvm.log2.", - .@"llvm.round.", - .@"llvm.sin.", - .@"llvm.sqrt.", - .@"llvm.trunc.", - .@"llvm.bitreverse.", - .@"llvm.bswap.", - .@"llvm.ctpop.", => @as(Value, @enumFromInt(instruction.data)).typeOfWip(wip), .getelementptr, .@"getelementptr inbounds", @@ -2762,7 +3529,6 @@ pub const Function = struct { }, .unimplemented => @enumFromInt(instruction.data), .va_arg => wip.extraData(VaArg, instruction.data).type, - .@"llvm.fma." => wip.extraData(FusedMultiplyAdd, instruction.data).a.typeOfWip(wip), }; } @@ -2791,22 +3557,6 @@ pub const Function = struct { .@"frem fast", .fsub, .@"fsub fast", - .@"llvm.maxnum.", - .@"llvm.minnum.", - .@"llvm.ctlz.", - .@"llvm.cttz.", - .@"llvm.sadd.sat.", - .@"llvm.smax.", - .@"llvm.smin.", - .@"llvm.smul.fix.sat.", - .@"llvm.sshl.sat.", - .@"llvm.ssub.sat.", - .@"llvm.uadd.sat.", - .@"llvm.umax.", - .@"llvm.umin.", - .@"llvm.umul.fix.sat.", - .@"llvm.ushl.sat.", - .@"llvm.usub.sat.", .lshr, .@"lshr exact", .mul, @@ -2927,22 +3677,6 @@ pub const Function = struct { .changeScalarAssumeCapacity(.i1, builder), .fneg, .@"fneg fast", - .@"llvm.ceil.", - .@"llvm.cos.", - .@"llvm.exp.", - .@"llvm.exp2.", - .@"llvm.fabs.", - .@"llvm.floor.", - .@"llvm.log.", - .@"llvm.log10.", - .@"llvm.log2.", - .@"llvm.round.", - .@"llvm.sin.", - .@"llvm.sqrt.", - .@"llvm.trunc.", - .@"llvm.bitreverse.", - .@"llvm.bswap.", - .@"llvm.ctpop.", => @as(Value, @enumFromInt(instruction.data)).typeOf(function_index, builder), .getelementptr, .@"getelementptr inbounds", @@ -2981,7 +3715,6 @@ pub const Function = struct { }, .unimplemented => @enumFromInt(instruction.data), .va_arg => function.extraData(VaArg, instruction.data).type, - .@"llvm.fma." => function.extraData(FusedMultiplyAdd, instruction.data).a.typeOf(function_index, builder), }; } @@ -3074,12 +3807,6 @@ pub const Function = struct { mask: Value, }; - pub const FusedMultiplyAdd = struct { - a: Value, - b: Value, - c: Value, - }; - pub const ExtractValue = struct { val: Value, indices_len: u32, @@ -3487,24 +4214,7 @@ pub const WipFunction = struct { switch (tag) { .fneg, .@"fneg fast", - .@"llvm.ceil.", - .@"llvm.cos.", - .@"llvm.exp.", - .@"llvm.exp2.", - .@"llvm.fabs.", - .@"llvm.floor.", - .@"llvm.log.", - .@"llvm.log10.", - .@"llvm.log2.", - .@"llvm.round.", - .@"llvm.sin.", - .@"llvm.sqrt.", - .@"llvm.trunc.", => assert(val.typeOfWip(self).scalarType(self.builder).isFloatingPoint()), - .@"llvm.bitreverse.", - .@"llvm.bswap.", - .@"llvm.ctpop.", - => assert(val.typeOfWip(self).scalarType(self.builder).isInteger(self.builder)), else => unreachable, } try self.ensureUnusedExtraCapacity(1, NoExtra, 0); @@ -3513,43 +4223,10 @@ pub const WipFunction = struct { switch (tag) { .fneg => self.llvm.builder.setFastMath(false), .@"fneg fast" => self.llvm.builder.setFastMath(true), - .@"llvm.ceil.", - .@"llvm.cos.", - .@"llvm.exp.", - .@"llvm.exp2.", - .@"llvm.fabs.", - .@"llvm.floor.", - .@"llvm.log.", - .@"llvm.log10.", - .@"llvm.log2.", - .@"llvm.round.", - .@"llvm.sin.", - .@"llvm.sqrt.", - .@"llvm.trunc.", - .@"llvm.bitreverse.", - .@"llvm.bswap.", - .@"llvm.ctpop.", - => {}, else => unreachable, } self.llvm.instructions.appendAssumeCapacity(switch (tag) { .fneg, .@"fneg fast" => &llvm.Builder.buildFNeg, - .@"llvm.ceil." => &llvm.Builder.buildCeil, - .@"llvm.cos." => &llvm.Builder.buildCos, - .@"llvm.exp." => &llvm.Builder.buildExp, - .@"llvm.exp2." => &llvm.Builder.buildExp2, - .@"llvm.fabs." => &llvm.Builder.buildFAbs, - .@"llvm.floor." => &llvm.Builder.buildFloor, - .@"llvm.log." => &llvm.Builder.buildLog, - .@"llvm.log10." => &llvm.Builder.buildLog10, - .@"llvm.log2." => &llvm.Builder.buildLog2, - .@"llvm.round." => &llvm.Builder.buildRound, - .@"llvm.sin." => &llvm.Builder.buildSin, - .@"llvm.sqrt." => &llvm.Builder.buildSqrt, - .@"llvm.trunc." => &llvm.Builder.buildFTrunc, - .@"llvm.bitreverse." => &llvm.Builder.buildBitReverse, - .@"llvm.bswap." => &llvm.Builder.buildBSwap, - .@"llvm.ctpop." => &llvm.Builder.buildCTPop, else => unreachable, }(self.llvm.builder, val.toLlvm(self), instruction.llvmName(self))); } @@ -3593,20 +4270,6 @@ pub const WipFunction = struct { .@"frem fast", .fsub, .@"fsub fast", - .@"llvm.maxnum.", - .@"llvm.minnum.", - .@"llvm.sadd.sat.", - .@"llvm.smax.", - .@"llvm.smin.", - .@"llvm.smul.fix.sat.", - .@"llvm.sshl.sat.", - .@"llvm.ssub.sat.", - .@"llvm.uadd.sat.", - .@"llvm.umax.", - .@"llvm.umin.", - .@"llvm.umul.fix.sat.", - .@"llvm.ushl.sat.", - .@"llvm.usub.sat.", .lshr, .@"lshr exact", .mul, @@ -3627,9 +4290,6 @@ pub const WipFunction = struct { .urem, .xor, => assert(lhs.typeOfWip(self) == rhs.typeOfWip(self)), - .@"llvm.ctlz.", - .@"llvm.cttz.", - => assert(lhs.typeOfWip(self).scalarType(self.builder).isInteger(self.builder) and rhs.typeOfWip(self) == .i1), else => unreachable, } try self.ensureUnusedExtraCapacity(1, Instruction.Binary, 0); @@ -3665,22 +4325,6 @@ pub const WipFunction = struct { .fmul, .@"fmul fast" => &llvm.Builder.buildFMul, .frem, .@"frem fast" => &llvm.Builder.buildFRem, .fsub, .@"fsub fast" => &llvm.Builder.buildFSub, - .@"llvm.maxnum." => &llvm.Builder.buildMaxNum, - .@"llvm.minnum." => &llvm.Builder.buildMinNum, - .@"llvm.ctlz." => &llvm.Builder.buildCTLZ, - .@"llvm.cttz." => &llvm.Builder.buildCTTZ, - .@"llvm.sadd.sat." => &llvm.Builder.buildSAddSat, - .@"llvm.smax." => &llvm.Builder.buildSMax, - .@"llvm.smin." => &llvm.Builder.buildSMin, - .@"llvm.smul.fix.sat." => &llvm.Builder.buildSMulFixSat, - .@"llvm.sshl.sat." => &llvm.Builder.buildSShlSat, - .@"llvm.ssub.sat." => &llvm.Builder.buildSSubSat, - .@"llvm.uadd.sat." => &llvm.Builder.buildUAddSat, - .@"llvm.umax." => &llvm.Builder.buildUMax, - .@"llvm.umin." => &llvm.Builder.buildUMin, - .@"llvm.umul.fix.sat." => &llvm.Builder.buildUMulFixSat, - .@"llvm.ushl.sat." => &llvm.Builder.buildUShlSat, - .@"llvm.usub.sat." => &llvm.Builder.buildUSubSat, .lshr => &llvm.Builder.buildLShr, .@"lshr exact" => &llvm.Builder.buildLShrExact, .mul => &llvm.Builder.buildMul, @@ -4419,7 +5063,7 @@ pub const WipFunction = struct { self: *WipFunction, function_attributes: FunctionAttributes, ty: Type, - kind: Constant.Asm.Info, + kind: Constant.Assembly.Info, assembly: String, constraints: String, args: []const Value, @@ -4429,6 +5073,25 @@ pub const WipFunction = struct { return self.call(.normal, CallConv.default, function_attributes, ty, callee, args, name); } + pub fn callIntrinsic( + self: *WipFunction, + id: Intrinsic, + overload: []const Type, + args: []const Value, + name: []const u8, + ) Allocator.Error!Value { + const intrinsic = try self.builder.getIntrinsic(id, overload); + return self.call( + .normal, + CallConv.default, + .none, + intrinsic.typeOf(self.builder), + intrinsic.toValue(self.builder), + args, + name, + ); + } + pub fn vaArg(self: *WipFunction, list: Value, ty: Type, name: []const u8) Allocator.Error!Value { try self.ensureUnusedExtraCapacity(1, Instruction.VaArg, 0); const instruction = try self.addInst(name, .{ @@ -4448,29 +5111,6 @@ pub const WipFunction = struct { return instruction.toValue(); } - pub fn fusedMultiplyAdd(self: *WipFunction, a: Value, b: Value, c: Value) Allocator.Error!Value { - assert(a.typeOfWip(self) == b.typeOfWip(self) and a.typeOfWip(self) == c.typeOfWip(self)); - try self.ensureUnusedExtraCapacity(1, Instruction.FusedMultiplyAdd, 0); - const instruction = try self.addInst("", .{ - .tag = .@"llvm.fma.", - .data = self.addExtraAssumeCapacity(Instruction.FusedMultiplyAdd{ - .a = a, - .b = b, - .c = c, - }), - }); - if (self.builder.useLibLlvm()) { - self.llvm.instructions.appendAssumeCapacity(llvm.Builder.buildFMA( - self.llvm.builder, - a.toLlvm(self), - b.toLlvm(self), - c.toLlvm(self), - instruction.llvmName(self), - )); - } - return instruction.toValue(); - } - pub const WipUnimplemented = struct { instruction: Instruction.Index, @@ -4697,22 +5337,6 @@ pub const WipFunction = struct { .@"icmp ugt", .@"icmp ule", .@"icmp ult", - .@"llvm.maxnum.", - .@"llvm.minnum.", - .@"llvm.ctlz.", - .@"llvm.cttz.", - .@"llvm.sadd.sat.", - .@"llvm.smax.", - .@"llvm.smin.", - .@"llvm.smul.fix.sat.", - .@"llvm.sshl.sat.", - .@"llvm.ssub.sat.", - .@"llvm.uadd.sat.", - .@"llvm.umax.", - .@"llvm.umin.", - .@"llvm.umul.fix.sat.", - .@"llvm.ushl.sat.", - .@"llvm.usub.sat.", .lshr, .@"lshr exact", .mul, @@ -4828,22 +5452,6 @@ pub const WipFunction = struct { .fneg, .@"fneg fast", .ret, - .@"llvm.ceil.", - .@"llvm.cos.", - .@"llvm.exp.", - .@"llvm.exp2.", - .@"llvm.fabs.", - .@"llvm.floor.", - .@"llvm.log.", - .@"llvm.log10.", - .@"llvm.log2.", - .@"llvm.round.", - .@"llvm.sin.", - .@"llvm.sqrt.", - .@"llvm.trunc.", - .@"llvm.bitreverse.", - .@"llvm.bswap.", - .@"llvm.ctpop.", => instruction.data = @intFromEnum(instructions.map(@enumFromInt(instruction.data))), .getelementptr, .@"getelementptr inbounds", @@ -4949,14 +5557,6 @@ pub const WipFunction = struct { .type = extra.type, }); }, - .@"llvm.fma." => { - const extra = self.extraData(Instruction.FusedMultiplyAdd, instruction.data); - instruction.data = wip_extra.addExtra(Instruction.FusedMultiplyAdd{ - .a = instructions.map(extra.a), - .b = instructions.map(extra.b), - .c = instructions.map(extra.c), - }); - }, } function.instructions.appendAssumeCapacity(instruction); names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip) @@ -5627,7 +6227,7 @@ pub const Constant = enum(u32) { rhs: Constant, }; - pub const Asm = extern struct { + pub const Assembly = extern struct { type: Type, assembly: String, constraints: String, @@ -5651,7 +6251,7 @@ pub const Constant = enum(u32) { } pub fn toValue(self: Constant) Value { - return @enumFromInt(@intFromEnum(Value.first_constant) + @intFromEnum(self)); + return @enumFromInt(Value.first_constant + @intFromEnum(self)); } pub fn typeOf(self: Constant, builder: *Builder) Type { @@ -6139,7 +6739,7 @@ pub const Constant = enum(u32) { .@"asm alignstack inteldialect unwind", .@"asm sideeffect alignstack inteldialect unwind", => |tag| { - const extra = data.builder.constantExtraData(Asm, item.data); + const extra = data.builder.constantExtraData(Assembly, item.data); try writer.print("{s} {\"}, {\"}", .{ @tagName(tag), extra.assembly.fmt(data.builder), @@ -6166,18 +6766,20 @@ pub const Constant = enum(u32) { pub const Value = enum(u32) { none = std.math.maxInt(u31), + false = first_constant + @intFromEnum(Constant.false), + true = first_constant + @intFromEnum(Constant.true), _, - const first_constant: Value = @enumFromInt(1 << 31); + const first_constant = 1 << 31; pub fn unwrap(self: Value) union(enum) { instruction: Function.Instruction.Index, constant: Constant, } { - return if (@intFromEnum(self) < @intFromEnum(first_constant)) + return if (@intFromEnum(self) < first_constant) .{ .instruction = @enumFromInt(@intFromEnum(self)) } else - .{ .constant = @enumFromInt(@intFromEnum(self) - @intFromEnum(first_constant)) }; + .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }; } pub fn typeOfWip(self: Value, wip: *const WipFunction) Type { @@ -6349,8 +6951,11 @@ pub fn init(options: Options) InitError!Builder { inline for (.{ 1, 8, 16, 29, 32, 64, 80, 128 }) |bits| assert(self.intTypeAssumeCapacity(bits) == @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); - inline for (.{0}) |addr_space| - assert(self.ptrTypeAssumeCapacity(@enumFromInt(addr_space)) == .ptr); + inline for (.{ 0, 4 }) |addr_space_index| { + const addr_space: AddrSpace = @enumFromInt(addr_space_index); + assert(self.ptrTypeAssumeCapacity(addr_space) == + @field(Type, std.fmt.comptimePrint("ptr{ }", .{addr_space}))); + } } { @@ -6883,17 +7488,136 @@ pub fn getGlobal(self: *const Builder, name: String) ?Global.Index { return @enumFromInt(self.globals.getIndex(name) orelse return null); } +pub fn addFunction(self: *Builder, ty: Type, name: String) Allocator.Error!Function.Index { + assert(!name.isAnon()); + try self.ensureUnusedTypeCapacity(1, NoExtra, 0); + try self.ensureUnusedGlobalCapacity(name); + try self.functions.ensureUnusedCapacity(self.gpa, 1); + return self.addFunctionAssumeCapacity(ty, name); +} + +pub fn addFunctionAssumeCapacity(self: *Builder, ty: Type, name: String) Function.Index { + assert(ty.isFunction(self)); + if (self.useLibLlvm()) self.llvm.globals.appendAssumeCapacity( + self.llvm.module.?.addFunction(name.slice(self).?, ty.toLlvm(self)), + ); + const function_index: Function.Index = @enumFromInt(self.functions.items.len); + self.functions.appendAssumeCapacity(.{ .global = self.addGlobalAssumeCapacity(name, .{ + .type = ty, + .kind = .{ .function = function_index }, + }) }); + return function_index; +} + +pub fn getIntrinsic( + self: *Builder, + id: Intrinsic, + overload: []const Type, +) Allocator.Error!Function.Index { + const ExpectedContents = extern union { + name: [expected_intrinsic_name_len]u8, + attrs: extern struct { + params: [expected_args_len]Type, + fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes, + attrs: [expected_attrs_len]Attribute.Index, + fields: [expected_fields_len]Type, + }, + }; + var stack align(@max(@alignOf(std.heap.StackFallbackAllocator(0)), @alignOf(ExpectedContents))) = + std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); + const allocator = stack.get(); + + const name = name: { + var buffer = std.ArrayList(u8).init(allocator); + defer buffer.deinit(); + + try buffer.writer().print("llvm.{s}", .{@tagName(id)}); + for (overload) |ty| try buffer.writer().print(".{m}", .{ty.fmt(self)}); + break :name try self.string(buffer.items); + }; + if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; + + const signature = Intrinsic.signatures.get(id); + const param_types = try allocator.alloc(Type, signature.params.len); + defer allocator.free(param_types); + const function_attributes = + try allocator.alloc(Attributes, FunctionAttributes.return_index + signature.params.len); + defer allocator.free(function_attributes); + + var attributes: struct { + builder: *Builder, + list: std.ArrayList(Attribute.Index), + + fn deinit(state: *@This()) void { + state.list.deinit(); + state.* = undefined; + } + + fn get(state: *@This(), attributes: []const Attribute) Allocator.Error!Attributes { + try state.list.resize(attributes.len); + for (state.list.items, attributes) |*item, attribute| + item.* = try state.builder.attr(attribute); + return state.builder.attrs(state.list.items); + } + } = .{ .builder = self, .list = std.ArrayList(Attribute.Index).init(allocator) }; + defer attributes.deinit(); + + var overload_index: usize = 0; + function_attributes[FunctionAttributes.function_index] = try attributes.get(signature.attrs); + for ( + param_types, + function_attributes[FunctionAttributes.return_index..], + signature.params, + ) |*param_type, *param_attributes, signature_param| { + switch (signature_param.kind) { + .type => |ty| param_type.* = ty, + .overloaded => { + param_type.* = overload[overload_index]; + overload_index += 1; + }, + .overloaded_tuple => |len| { + const fields = try allocator.alloc(Type, len); + defer allocator.free(fields); + for (fields, overload[overload_index..][0..len]) |*field, ty| field.* = ty; + param_type.* = try self.structType(.normal, fields); + overload_index += len; + }, + .matches, .matches_tuple, .matches_with_overflow => {}, + } + param_attributes.* = try attributes.get(signature_param.attrs); + } + assert(overload_index == overload.len); + for (param_types, signature.params) |*param_type, signature_param| switch (signature_param.kind) { + .type, .overloaded, .overloaded_tuple => {}, + .matches => |param_index| param_type.* = param_types[param_index], + .matches_tuple => |tuple| param_type.* = + param_types[tuple.param].structFields(self)[tuple.field], + .matches_with_overflow => |param_index| { + const ty = param_types[param_index]; + param_type.* = try self.structType(.normal, &.{ ty, try ty.changeScalar(.i1, self) }); + }, + }; + + const function_index = + try self.addFunction(try self.fnType(param_types[0], param_types[1..], .normal), name); + function_index.ptr(self).attributes = try self.fnAttrs(function_attributes); + return function_index; +} + pub fn intConst(self: *Builder, ty: Type, value: anytype) Allocator.Error!Constant { + const int_value = switch (@typeInfo(@TypeOf(value))) { + .Int, .ComptimeInt => value, + .Enum => @intFromEnum(value), + else => @compileError("intConst expected an integral value, got " ++ @typeName(@TypeOf(value))), + }; var limbs: [ - switch (@typeInfo(@TypeOf(value))) { + switch (@typeInfo(@TypeOf(int_value))) { .Int => |info| std.math.big.int.calcTwosCompLimbCount(info.bits), - .ComptimeInt => std.math.big.int.calcLimbLen(value), - else => @compileError( - "intConst expected an integral value, got " ++ @typeName(@TypeOf(value)), - ), + .ComptimeInt => std.math.big.int.calcLimbLen(int_value), + else => unreachable, } ]std.math.big.Limb = undefined; - return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, value).toConst()); + return self.bigIntConst(ty, std.math.big.int.Mutable.init(&limbs, int_value).toConst()); } pub fn intValue(self: *Builder, ty: Type, value: anytype) Allocator.Error!Value { @@ -7304,18 +8028,18 @@ pub fn binValue(self: *Builder, tag: Constant.Tag, lhs: Constant, rhs: Constant) pub fn asmConst( self: *Builder, ty: Type, - info: Constant.Asm.Info, + info: Constant.Assembly.Info, assembly: String, constraints: String, ) Allocator.Error!Constant { - try self.ensureUnusedConstantCapacity(1, Constant.Asm, 0); + try self.ensureUnusedConstantCapacity(1, Constant.Assembly, 0); return self.asmConstAssumeCapacity(ty, info, assembly, constraints); } pub fn asmValue( self: *Builder, ty: Type, - info: Constant.Asm.Info, + info: Constant.Assembly.Info, assembly: String, constraints: String, ) Allocator.Error!Value { @@ -7413,7 +8137,7 @@ pub fn printUnbuffered( if (variable.global.getReplacement(self) != .none) continue; const global = variable.global.ptrConst(self); try writer.print( - \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{, } + \\{} ={}{}{}{}{}{}{ }{} {s} {%}{ }{, } \\ , .{ variable.global.fmt(self), @@ -7472,7 +8196,9 @@ pub fn printUnbuffered( function.attributes.param(arg, self).fmt(self), }); if (function.instructions.len > 0) - try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}); + try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}) + else + try writer.print(" %{d}", .{arg}); } switch (global.type.functionKind(self)) { .normal => {}, @@ -7481,11 +8207,11 @@ pub fn printUnbuffered( try writer.writeAll("..."); }, } - try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space }); + try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space }); if (function_attributes != .none) try writer.print(" #{d}", .{ (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, }); - try writer.print("{}", .{function.alignment}); + try writer.print("{ }", .{function.alignment}); if (function.instructions.len > 0) { var block_incoming_len: u32 = undefined; try writer.writeAll(" {\n"); @@ -7735,33 +8461,6 @@ pub fn printUnbuffered( val.fmt(function_index, self), }); }, - .@"llvm.ceil.", - .@"llvm.cos.", - .@"llvm.exp.", - .@"llvm.exp2.", - .@"llvm.fabs.", - .@"llvm.floor.", - .@"llvm.log.", - .@"llvm.log10.", - .@"llvm.log2.", - .@"llvm.round.", - .@"llvm.sin.", - .@"llvm.sqrt.", - .@"llvm.trunc.", - .@"llvm.bitreverse.", - .@"llvm.bswap.", - .@"llvm.ctpop.", - => |tag| { - const val: Value = @enumFromInt(instruction.data); - const ty = val.typeOf(function_index, self); - try writer.print(" %{} = call {%} @{s}{m}({%})\n", .{ - instruction_index.name(&function).fmt(self), - ty.fmt(self), - @tagName(tag), - ty.fmt(self), - val.fmt(function_index, self), - }); - }, .getelementptr, .@"getelementptr inbounds", => |tag| { @@ -7809,41 +8508,6 @@ pub fn printUnbuffered( for (indices) |index| try writer.print(", {d}", .{index}); try writer.writeByte('\n'); }, - .@"llvm.maxnum.", - .@"llvm.minnum.", - .@"llvm.ctlz.", - .@"llvm.cttz.", - .@"llvm.sadd.sat.", - .@"llvm.smax.", - .@"llvm.smin.", - .@"llvm.smul.fix.sat.", - .@"llvm.sshl.sat.", - .@"llvm.ssub.sat.", - .@"llvm.uadd.sat.", - .@"llvm.umax.", - .@"llvm.umin.", - .@"llvm.umul.fix.sat.", - .@"llvm.ushl.sat.", - .@"llvm.usub.sat.", - => |tag| { - const extra = - function.extraData(Function.Instruction.Binary, instruction.data); - const ty = instruction_index.typeOf(function_index, self); - try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{ - instruction_index.name(&function).fmt(self), - ty.fmt(self), - @tagName(tag), - ty.fmt(self), - extra.lhs.fmt(function_index, self), - extra.rhs.fmt(function_index, self), - switch (tag) { - .@"llvm.smul.fix.sat.", - .@"llvm.umul.fix.sat.", - => ", i32 0", - else => "", - }, - }); - }, .load, .@"load atomic", .@"load atomic volatile", @@ -7984,20 +8648,6 @@ pub fn printUnbuffered( extra.type.fmt(self), }); }, - .@"llvm.fma." => |tag| { - const extra = - function.extraData(Function.Instruction.FusedMultiplyAdd, instruction.data); - const ty = instruction_index.typeOf(function_index, self); - try writer.print(" %{} = call {%} @{s}{m}({%}, {%}, {%})\n", .{ - instruction_index.name(&function).fmt(self), - ty.fmt(self), - @tagName(tag), - ty.fmt(self), - extra.a.fmt(function_index, self), - extra.b.fmt(function_index, self), - extra.c.fmt(function_index, self), - }); - }, } } try writer.writeByte('}'); @@ -9623,13 +10273,13 @@ fn binConstAssumeCapacity( fn asmConstAssumeCapacity( self: *Builder, ty: Type, - info: Constant.Asm.Info, + info: Constant.Assembly.Info, assembly: String, constraints: String, ) Constant { assert(ty.functionKind(self) == .normal); - const Key = struct { tag: Constant.Tag, extra: Constant.Asm }; + const Key = struct { tag: Constant.Tag, extra: Constant.Assembly }; const Adapter = struct { builder: *const Builder, pub fn hash(_: @This(), key: Key) u32 { @@ -9641,7 +10291,7 @@ fn asmConstAssumeCapacity( pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; - const rhs_extra = ctx.builder.constantExtraData(Constant.Asm, rhs_data); + const rhs_extra = ctx.builder.constantExtraData(Constant.Assembly, rhs_data); return std.meta.eql(lhs_key.extra, rhs_extra); } }; diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index fd111ac94f..9220c30a09 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -345,9 +345,6 @@ pub const Value = opaque { pub const addSretAttr = ZigLLVMAddSretAttr; extern fn ZigLLVMAddSretAttr(fn_ref: *Value, type_val: *Type) void; - pub const setCallSret = ZigLLVMSetCallSret; - extern fn ZigLLVMSetCallSret(Call: *Value, return_type: *Type) void; - pub const getParam = LLVMGetParam; extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; @@ -488,9 +485,6 @@ pub const Module = opaque { pub const getNamedFunction = LLVMGetNamedFunction; extern fn LLVMGetNamedFunction(*Module, Name: [*:0]const u8) ?*Value; - pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration; - extern fn LLVMGetIntrinsicDeclaration(Mod: *Module, ID: c_uint, ParamTypes: ?[*]const *Type, ParamCount: usize) *Value; - pub const printToString = LLVMPrintModuleToString; extern fn LLVMPrintModuleToString(*Module) [*:0]const u8; @@ -664,18 +658,6 @@ pub const Builder = opaque { Name: [*:0]const u8, ) *Value; - pub const buildCallOld = ZigLLVMBuildCall; - extern fn ZigLLVMBuildCall( - *Builder, - *Type, - Fn: *Value, - Args: [*]const *Value, - NumArgs: c_uint, - CC: CallConv, - attr: CallAttr, - Name: [*:0]const u8, - ) *Value; - pub const buildRetVoid = LLVMBuildRetVoid; extern fn LLVMBuildRetVoid(*Builder) *Value; @@ -712,12 +694,6 @@ pub const Builder = opaque { pub const buildNUWAdd = LLVMBuildNUWAdd; extern fn LLVMBuildNUWAdd(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildSAddSat = ZigLLVMBuildSAddSat; - extern fn ZigLLVMBuildSAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - - pub const buildUAddSat = ZigLLVMBuildUAddSat; - extern fn ZigLLVMBuildUAddSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildFSub = LLVMBuildFSub; extern fn LLVMBuildFSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; @@ -733,12 +709,6 @@ pub const Builder = opaque { pub const buildNUWSub = LLVMBuildNUWSub; extern fn LLVMBuildNUWSub(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildSSubSat = ZigLLVMBuildSSubSat; - extern fn ZigLLVMBuildSSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - - pub const buildUSubSat = ZigLLVMBuildUSubSat; - extern fn ZigLLVMBuildUSubSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildFMul = LLVMBuildFMul; extern fn LLVMBuildFMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; @@ -751,12 +721,6 @@ pub const Builder = opaque { pub const buildNUWMul = LLVMBuildNUWMul; extern fn LLVMBuildNUWMul(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildSMulFixSat = ZigLLVMBuildSMulFixSat; - extern fn ZigLLVMBuildSMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - - pub const buildUMulFixSat = ZigLLVMBuildUMulFixSat; - extern fn ZigLLVMBuildUMulFixSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildUDiv = LLVMBuildUDiv; extern fn LLVMBuildUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; @@ -799,21 +763,12 @@ pub const Builder = opaque { pub const buildNSWShl = ZigLLVMBuildNSWShl; extern fn ZigLLVMBuildNSWShl(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildSShlSat = ZigLLVMBuildSShlSat; - extern fn ZigLLVMBuildSShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - - pub const buildUShlSat = ZigLLVMBuildUShlSat; - extern fn ZigLLVMBuildUShlSat(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildOr = LLVMBuildOr; extern fn LLVMBuildOr(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; pub const buildXor = LLVMBuildXor; extern fn LLVMBuildXor(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; - pub const buildIntCast2 = LLVMBuildIntCast2; - extern fn LLVMBuildIntCast2(*Builder, Val: *Value, DestTy: *Type, IsSigned: Bool, Name: [*:0]const u8) *Value; - pub const buildBitCast = LLVMBuildBitCast; extern fn LLVMBuildBitCast(*Builder, Val: *Value, DestTy: *Type, Name: [*:0]const u8) *Value; @@ -1020,81 +975,6 @@ pub const Builder = opaque { is_volatile: bool, ) *Value; - pub const buildMaxNum = ZigLLVMBuildMaxNum; - extern fn ZigLLVMBuildMaxNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildMinNum = ZigLLVMBuildMinNum; - extern fn ZigLLVMBuildMinNum(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildCeil = ZigLLVMBuildCeil; - extern fn ZigLLVMBuildCeil(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildCos = ZigLLVMBuildCos; - extern fn ZigLLVMBuildCos(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildExp = ZigLLVMBuildExp; - extern fn ZigLLVMBuildExp(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildExp2 = ZigLLVMBuildExp2; - extern fn ZigLLVMBuildExp2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildFAbs = ZigLLVMBuildFAbs; - extern fn ZigLLVMBuildFAbs(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildFloor = ZigLLVMBuildFloor; - extern fn ZigLLVMBuildFloor(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildLog = ZigLLVMBuildLog; - extern fn ZigLLVMBuildLog(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildLog10 = ZigLLVMBuildLog10; - extern fn ZigLLVMBuildLog10(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildLog2 = ZigLLVMBuildLog2; - extern fn ZigLLVMBuildLog2(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildRound = ZigLLVMBuildRound; - extern fn ZigLLVMBuildRound(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildSin = ZigLLVMBuildSin; - extern fn ZigLLVMBuildSin(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildSqrt = ZigLLVMBuildSqrt; - extern fn ZigLLVMBuildSqrt(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildFTrunc = ZigLLVMBuildFTrunc; - extern fn ZigLLVMBuildFTrunc(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildBitReverse = ZigLLVMBuildBitReverse; - extern fn ZigLLVMBuildBitReverse(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildBSwap = ZigLLVMBuildBSwap; - extern fn ZigLLVMBuildBSwap(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildCTPop = ZigLLVMBuildCTPop; - extern fn ZigLLVMBuildCTPop(builder: *Builder, V: *Value, name: [*:0]const u8) *Value; - - pub const buildCTLZ = ZigLLVMBuildCTLZ; - extern fn ZigLLVMBuildCTLZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildCTTZ = ZigLLVMBuildCTTZ; - extern fn ZigLLVMBuildCTTZ(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildFMA = ZigLLVMBuildFMA; - extern fn ZigLLVMBuildFMA(builder: *Builder, a: *Value, b: *Value, c: *Value, name: [*:0]const u8) *Value; - - pub const buildUMax = ZigLLVMBuildUMax; - extern fn ZigLLVMBuildUMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildUMin = ZigLLVMBuildUMin; - extern fn ZigLLVMBuildUMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildSMax = ZigLLVMBuildSMax; - extern fn ZigLLVMBuildSMax(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - - pub const buildSMin = ZigLLVMBuildSMin; - extern fn ZigLLVMBuildSMin(builder: *Builder, LHS: *Value, RHS: *Value, name: [*:0]const u8) *Value; - pub const buildExactUDiv = LLVMBuildExactUDiv; extern fn LLVMBuildExactUDiv(*Builder, LHS: *Value, RHS: *Value, Name: [*:0]const u8) *Value; @@ -1563,9 +1443,6 @@ extern fn ZigLLVMWriteImportLibrary( kill_at: bool, ) bool; -pub const setCallElemTypeAttr = ZigLLVMSetCallElemTypeAttr; -extern fn ZigLLVMSetCallElemTypeAttr(Call: *Value, arg_index: usize, return_type: *Type) void; - pub const Linkage = enum(c_uint) { External, AvailableExternally, @@ -1784,9 +1661,6 @@ pub const DIGlobalVariable = opaque { pub const DIGlobalVariableExpression = opaque { pub const getVariable = ZigLLVMGlobalGetVariable; extern fn ZigLLVMGlobalGetVariable(global_variable: *DIGlobalVariableExpression) *DIGlobalVariable; - - pub const getExpression = ZigLLVMGlobalGetExpression; - extern fn ZigLLVMGlobalGetExpression(global_variable: *DIGlobalVariableExpression) *DIGlobalExpression; }; pub const DIType = opaque { pub const toScope = ZigLLVMTypeToScope; diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index e6568e97a8..5b599d8e0e 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -78,30 +78,6 @@ using namespace llvm; -void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) { - initializeLoopStrengthReducePass(*unwrap(R)); -} - -void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) { - initializeLowerIntrinsicsPass(*unwrap(R)); -} - -char *ZigLLVMGetHostCPUName(void) { - return strdup((const char *)sys::getHostCPUName().bytes_begin()); -} - -char *ZigLLVMGetNativeFeatures(void) { - SubtargetFeatures features; - - StringMap host_features; - if (sys::getHostCPUFeatures(host_features)) { - for (auto &F : host_features) - features.AddFeature(F.first(), F.second); - } - - return strdup((const char *)StringRef(features.getString()).bytes_begin()); -} - #ifndef NDEBUG static const bool assertions_on = true; #else @@ -179,14 +155,6 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri return reinterpret_cast(TM); } -unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD) { - return unwrap(TD)->getStackAlignment().value(); -} - -unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { - return unwrap(TD)->getProgramAddressSpace(); -} - namespace { // LLVM's time profiler can provide a hierarchy view of the time spent // in each component. It generates JSON report in Chrome's "Trace Event" @@ -410,12 +378,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM return false; } -ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { - return wrap(Type::getTokenTy(*unwrap(context_ref))); -} - - -ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) { +void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) { static OptBisect opt_bisect; opt_bisect.setLimit(limit); unwrap(context_ref)->setOptPassGate(opt_bisect); @@ -426,35 +389,23 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, return wrap(func); } -LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, - const char *Name) -{ - FunctionType *FTy = unwrap(Ty); - CallInst *call_inst = unwrap(B)->CreateCall(FTy, unwrap(Fn), - ArrayRef(unwrap(Args), NumArgs), Name); - call_inst->setCallingConv(static_cast(CC)); - switch (attr) { - case ZigLLVM_CallAttrAuto: +void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind) { + CallInst::TailCallKind TCK; + switch (TailCallKind) { + case ZigLLVMTailCallKindNone: + TCK = CallInst::TCK_None; break; - case ZigLLVM_CallAttrNeverTail: - call_inst->setTailCallKind(CallInst::TCK_NoTail); + case ZigLLVMTailCallKindTail: + TCK = CallInst::TCK_Tail; break; - case ZigLLVM_CallAttrNeverInline: - call_inst->addFnAttr(Attribute::NoInline); + case ZigLLVMTailCallKindMustTail: + TCK = CallInst::TCK_MustTail; break; - case ZigLLVM_CallAttrAlwaysTail: - call_inst->setTailCallKind(CallInst::TCK_MustTail); - break; - case ZigLLVM_CallAttrAlwaysInline: - call_inst->addFnAttr(Attribute::AlwaysInline); + case ZigLLVMTailCallKindNoTail: + TCK = CallInst::TCK_NoTail; break; } - return wrap(call_inst); -} - -ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, CallInst::TailCallKind TailCallKind) { - unwrap(Call)->setTailCallKind(TailCallKind); + unwrap(Call)->setTailCallKind(TCK); } void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) { @@ -481,188 +432,6 @@ LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef return wrap(call_inst); } -LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ceil, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::cos, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::exp2, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::fabs, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::floor, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log10, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::log2, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::round, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sin, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::sqrt, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::trunc, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bitreverse, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::bswap, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef B, LLVMValueRef V, const char *name) { - CallInst *call_inst = unwrap(B)->CreateUnaryIntrinsic(Intrinsic::ctpop, unwrap(V), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ctlz, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::cttz, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char *name) { - llvm::Type* types[1] = { - unwrap(A)->getType(), - }; - llvm::Value* values[3] = {unwrap(A), unwrap(B), unwrap(C)}; - - CallInst *call_inst = unwrap(builder)->CreateIntrinsic(Intrinsic::fma, types, values, nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS), name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS), name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umax, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::umin, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smax, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::smin, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::uadd_sat, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ssub_sat, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::usub_sat, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - llvm::Type* types[1] = { - unwrap(LHS)->getType(), - }; - // pass scale = 0 as third argument - llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)}; - - CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::smul_fix_sat, types, values, nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - llvm::Type* types[1] = { - unwrap(LHS)->getType(), - }; - // pass scale = 0 as third argument - llvm::Value* values[3] = {unwrap(LHS), unwrap(RHS), unwrap(B)->getInt32(0)}; - - CallInst *call_inst = unwrap(B)->CreateIntrinsic(Intrinsic::umul_fix_sat, types, values, nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::sshl_sat, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - -LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { - CallInst *call_inst = unwrap(B)->CreateBinaryIntrinsic(Intrinsic::ushl_sat, unwrap(LHS), unwrap(RHS), nullptr, name); - return wrap(call_inst); -} - void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram) { assert( isa(unwrap(fn)) ); Function *unwrapped_function = reinterpret_cast(unwrap(fn)); @@ -1206,14 +975,6 @@ void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) { func->addParamAttrs(0, attr_builder); } -void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty) { - Function *func = unwrap(fn_ref); - AttrBuilder attr_builder(func->getContext()); - Type *llvm_type = unwrap(elem_ty); - attr_builder.addTypeAttr(Attribute::ElementType, llvm_type); - func->addParamAttrs(arg_index, attr_builder); -} - void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) { Function *func = unwrap(fn_ref); func->addFnAttr(attr_name, attr_value); @@ -1223,40 +984,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { cl::ParseCommandLineOptions(argc, argv); } -const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { - return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin(); -} - -const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor) { - return (const char*)Triple::getVendorTypeName((Triple::VendorType)vendor).bytes_begin(); -} - -const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os) { - const char* name = (const char*)Triple::getOSTypeName((Triple::OSType)os).bytes_begin(); - if (strcmp(name, "macosx") == 0) return "macos"; - return name; -} - -const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) { - return (const char*)Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type).bytes_begin(); -} - -void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, - ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, - ZigLLVM_ObjectFormatType *oformat) -{ - char *native_triple = LLVMGetDefaultTargetTriple(); - Triple triple(Triple::normalize(native_triple)); - - *arch_type = (ZigLLVM_ArchType)triple.getArch(); - *vendor_type = (ZigLLVM_VendorType)triple.getVendor(); - *os_type = (ZigLLVM_OSType)triple.getOS(); - *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment(); - *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat(); - - free(native_triple); -} - void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) { unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4); @@ -1314,50 +1041,6 @@ LLVMValueRef ZigLLVMBuildAllocaInAddressSpace(LLVMBuilderRef builder, LLVMTypeRe return wrap(unwrap(builder)->CreateAlloca(unwrap(Ty), AddressSpace, nullptr, Name)); } -void ZigLLVMSetTailCall(LLVMValueRef Call) { - unwrap(Call)->setTailCallKind(CallInst::TCK_MustTail); -} - -void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type) { - CallInst *call_inst = unwrap(Call); - Type *llvm_type = unwrap(return_type); - call_inst->addParamAttr(AttributeList::ReturnIndex, - Attribute::getWithStructRetType(call_inst->getContext(), llvm_type)); -} - -void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type) { - CallInst *call_inst = unwrap(Call); - Type *llvm_type = unwrap(return_type); - call_inst->addParamAttr(arg_index, - Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type)); -} - -void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { - unwrap(function)->setPrefixData(unwrap(data)); -} - -void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, ZigLLVM_CallingConv cc) { - unwrap(function)->setCallingConv(static_cast(cc)); -} - -class MyOStream: public raw_ostream { - public: - MyOStream(void (*_append_diagnostic)(void *, const char *, size_t), void *_context) : - raw_ostream(true), append_diagnostic(_append_diagnostic), context(_context), pos(0) { - - } - void write_impl(const char *ptr, size_t len) override { - append_diagnostic(context, ptr, len); - pos += len; - } - uint64_t current_pos() const override { - return pos; - } - void (*append_diagnostic)(void *, const char *, size_t); - void *context; - size_t pos; -}; - bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, const char *output_lib_path, bool kill_at) { @@ -1549,10 +1232,6 @@ ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpress return reinterpret_cast(reinterpret_cast(global_variable_expression)->getVariable()); } -ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression) { - return reinterpret_cast(reinterpret_cast(global_variable_expression)->getExpression()); -} - void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression) { unwrap(Val)->addDebugInfo(reinterpret_cast(global_variable_expression)); } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 3f5fefb85b..258e846032 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -43,13 +43,6 @@ struct ZigLLVMInsertionPoint; struct ZigLLVMDINode; struct ZigLLVMMDString; -ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); -ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); - -/// Caller must free memory with LLVMDisposeMessage -ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); -ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); - ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, char **error_message, bool is_debug, bool is_small, bool time_report, bool tsan, bool lto, @@ -67,13 +60,20 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel, bool function_sections, enum ZigLLVMABIType float_abi, const char *abi_name); -ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); - ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit); ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy, unsigned AddressSpace); +enum ZigLLVMTailCallKind { + ZigLLVMTailCallKindNone, + ZigLLVMTailCallKindTail, + ZigLLVMTailCallKindMustTail, + ZigLLVMTailCallKindNoTail, +}; + +ZIG_EXTERN_C void ZigLLVMSetTailCallKind(LLVMValueRef Call, enum ZigLLVMTailCallKind TailCallKind); + enum ZigLLVM_CallingConv { ZigLLVM_C = 0, ZigLLVM_Fast = 8, @@ -129,10 +129,6 @@ enum ZigLLVM_CallAttr { ZigLLVM_CallAttrAlwaysTail, ZigLLVM_CallAttrAlwaysInline, }; -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef function_type, - LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC, - enum ZigLLVM_CallAttr attr, const char *Name); - ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A); ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, @@ -141,47 +137,6 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemSet(LLVMBuilderRef B, LLVMValueRef Ptr, LLVMValueRef Val, LLVMValueRef Size, unsigned Align, bool isVolatile); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCeil(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCos(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildExp2(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFAbs(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFloor(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog10(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLog2(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildRound(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSin(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSqrt(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFTrunc(LLVMBuilderRef builder, LLVMValueRef V, const char* name); - -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBitReverse(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildBSwap(LLVMBuilderRef builder, LLVMValueRef V, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTPop(LLVMBuilderRef builder, LLVMValueRef V, const char* name); - -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTLZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCTTZ(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); - -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildFMA(LLVMBuilderRef builder, LLVMValueRef A, LLVMValueRef B, LLVMValueRef C, const char* name); - -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMaxNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMinNum(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); - -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMax(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMin(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSAddSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSSubSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUMulFixSat(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildUShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildSShlSat(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char* name); -ZIG_EXTERN_C LLVMValueRef LLVMBuildVectorSplat(LLVMBuilderRef B, unsigned elem_count, LLVMValueRef V, const char *Name); - - ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char *name); ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, @@ -345,22 +300,15 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu struct ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref); ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); -ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call); -ZIG_EXTERN_C void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type); -ZIG_EXTERN_C void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type); -ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data); -ZIG_EXTERN_C void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, enum ZigLLVM_CallingConv cc); ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val); ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val); -ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty); ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); ZIG_EXTERN_C ZigLLVMDIGlobalVariable* ZigLLVMGlobalGetVariable(ZigLLVMDIGlobalVariableExpression *global_variable_expression); -ZIG_EXTERN_C ZigLLVMDIGlobalExpression* ZigLLVMGlobalGetExpression(ZigLLVMDIGlobalVariableExpression *global_variable_expression); ZIG_EXTERN_C void ZigLLVMAttachMetaData(LLVMValueRef Val, ZigLLVMDIGlobalVariableExpression *global_variable_expression); @@ -610,11 +558,6 @@ ZIG_EXTERN_C void ZigLLVMTakeName(LLVMValueRef new_owner, LLVMValueRef victim); #define ZigLLVM_DIFlags_LittleEndian (1U << 28) #define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29) -ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch); -ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor); -ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os); -ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi); - ZIG_EXTERN_C bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output); ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output); ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output); @@ -625,11 +568,4 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch, const char *output_lib_path, bool kill_at); -ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, - enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type, - enum ZigLLVM_ObjectFormatType *oformat); - -ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD); -ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD); - #endif