diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-20 14:13:33 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-20 14:24:43 -0700 |
| commit | b9d3527e0ed53c4796ab64b4df7daf0909739807 (patch) | |
| tree | 6cb29ce60e606fc4cfd30dad8b6f88c07a6bf8a7 /src/codegen | |
| parent | 5dc251747b4ea65b1c8d3f2b5af62ca83c6d1196 (diff) | |
| download | zig-b9d3527e0ed53c4796ab64b4df7daf0909739807.tar.gz zig-b9d3527e0ed53c4796ab64b4df7daf0909739807.zip | |
stage2: implement comptime `@atomicRmw`
* introduce float_to_int and int_to_float AIR instructionts and
implement for the LLVM backend and C backend.
* Sema: implement `zirIntToFloat`.
* Sema: implement `@atomicRmw` comptime evaluation
- introduce `storePtrVal` for when one needs to store a Value to a
pointer which is a Value, and assert it happens at comptime.
* Value: introduce new functionality:
- intToFloat
- numberAddWrap
- numberSubWrap
- numberMax
- numberMin
- bitwiseAnd
- bitwiseNand (not implemented yet)
- bitwiseOr
- bitwiseXor
* Sema: hook up `zirBitwise` to the new Value bitwise implementations
* Type: rename `isFloat` to `isRuntimeFloat` because it returns `false`
for `comptime_float`.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 20 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 48 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 32 |
3 files changed, 94 insertions, 6 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 5eb4388a9e..6da791cb46 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -917,6 +917,8 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM .atomic_rmw => try airAtomicRmw(o, inst), .atomic_load => try airAtomicLoad(o, inst), + .int_to_float, .float_to_int => try airSimpleCast(o, inst), + .atomic_store_unordered => try airAtomicStore(o, inst, toMemoryOrder(.Unordered)), .atomic_store_monotonic => try airAtomicStore(o, inst, toMemoryOrder(.Monotonic)), .atomic_store_release => try airAtomicStore(o, inst, toMemoryOrder(.Release)), @@ -1899,6 +1901,24 @@ fn airArrayToSlice(o: *Object, inst: Air.Inst.Index) !CValue { return local; } +/// Emits a local variable with the result type and initializes it +/// with the operand. +fn airSimpleCast(o: *Object, inst: Air.Inst.Index) !CValue { + if (o.liveness.isUnused(inst)) + return CValue.none; + + const inst_ty = o.air.typeOfIndex(inst); + const local = try o.allocLocal(inst_ty, .Const); + const ty_op = o.air.instructions.items(.data)[inst].ty_op; + const writer = o.writer(); + const operand = try o.resolveInst(ty_op.operand); + + try writer.writeAll(" = "); + try o.writeCValue(writer, operand); + try writer.writeAll(";\n"); + return local; +} + fn airCmpxchg(o: *Object, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { const ty_pl = o.air.instructions.items(.data)[inst].ty_pl; const extra = o.air.extraData(Air.Cmpxchg, ty_pl.payload).data; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 53e57ee219..2e835260af 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1122,6 +1122,8 @@ pub const FuncGen = struct { .slice_ptr => try self.airSliceField(inst, 0), .slice_len => try self.airSliceField(inst, 1), .array_to_slice => try self.airArrayToSlice(inst), + .float_to_int => try self.airFloatToInt(inst), + .int_to_float => try self.airIntToFloat(inst), .cmpxchg_weak => try self.airCmpxchg(inst, true), .cmpxchg_strong => try self.airCmpxchg(inst, false), .fence => try self.airFence(inst), @@ -1372,6 +1374,40 @@ pub const FuncGen = struct { return self.builder.buildInsertValue(partial, len, 1, ""); } + fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) + return null; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const operand = try self.resolveInst(ty_op.operand); + const dest_ty = self.air.typeOfIndex(inst); + const dest_llvm_ty = try self.dg.llvmType(dest_ty); + + if (dest_ty.isSignedInt()) { + return self.builder.buildSIToFP(operand, dest_llvm_ty, ""); + } else { + return self.builder.buildUIToFP(operand, dest_llvm_ty, ""); + } + } + + fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) + return null; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const operand = try self.resolveInst(ty_op.operand); + const dest_ty = self.air.typeOfIndex(inst); + const dest_llvm_ty = try self.dg.llvmType(dest_ty); + + // TODO set fast math flag + + if (dest_ty.isSignedInt()) { + return self.builder.buildFPToSI(operand, dest_llvm_ty, ""); + } else { + return self.builder.buildFPToUI(operand, dest_llvm_ty, ""); + } + } + fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; @@ -1818,7 +1854,7 @@ pub const FuncGen = struct { const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.air.typeOfIndex(inst); - if (inst_ty.isFloat()) return self.builder.buildFAdd(lhs, rhs, ""); + if (inst_ty.isRuntimeFloat()) return self.builder.buildFAdd(lhs, rhs, ""); if (wrap) return self.builder.buildAdd(lhs, rhs, ""); if (inst_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, ""); return self.builder.buildNUWAdd(lhs, rhs, ""); @@ -1833,7 +1869,7 @@ pub const FuncGen = struct { const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.air.typeOfIndex(inst); - if (inst_ty.isFloat()) return self.builder.buildFSub(lhs, rhs, ""); + if (inst_ty.isRuntimeFloat()) return self.builder.buildFSub(lhs, rhs, ""); if (wrap) return self.builder.buildSub(lhs, rhs, ""); if (inst_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, ""); return self.builder.buildNUWSub(lhs, rhs, ""); @@ -1848,7 +1884,7 @@ pub const FuncGen = struct { const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.air.typeOfIndex(inst); - if (inst_ty.isFloat()) return self.builder.buildFMul(lhs, rhs, ""); + if (inst_ty.isRuntimeFloat()) return self.builder.buildFMul(lhs, rhs, ""); if (wrap) return self.builder.buildMul(lhs, rhs, ""); if (inst_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, ""); return self.builder.buildNUWMul(lhs, rhs, ""); @@ -1863,7 +1899,7 @@ pub const FuncGen = struct { const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.air.typeOfIndex(inst); - if (inst_ty.isFloat()) return self.builder.buildFDiv(lhs, rhs, ""); + if (inst_ty.isRuntimeFloat()) return self.builder.buildFDiv(lhs, rhs, ""); if (inst_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, ""); return self.builder.buildUDiv(lhs, rhs, ""); } @@ -1876,7 +1912,7 @@ pub const FuncGen = struct { const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.air.typeOfIndex(inst); - if (inst_ty.isFloat()) return self.builder.buildFRem(lhs, rhs, ""); + if (inst_ty.isRuntimeFloat()) return self.builder.buildFRem(lhs, rhs, ""); if (inst_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, ""); return self.builder.buildURem(lhs, rhs, ""); } @@ -2165,7 +2201,7 @@ pub const FuncGen = struct { const operand_ty = ptr_ty.elemType(); const operand = try self.resolveInst(extra.operand); const is_signed_int = operand_ty.isSignedInt(); - const is_float = operand_ty.isFloat(); + const is_float = operand_ty.isRuntimeFloat(); const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); const ordering = toLlvmAtomicOrdering(extra.ordering()); const single_threaded = llvm.Bool.fromBool(self.single_threaded); diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index db1dcd22f2..16445fa2d1 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -563,6 +563,38 @@ pub const Builder = opaque { ordering: AtomicOrdering, singleThread: Bool, ) *const Value; + + pub const buildFPToUI = LLVMBuildFPToUI; + extern fn LLVMBuildFPToUI( + *const Builder, + Val: *const Value, + DestTy: *const Type, + Name: [*:0]const u8, + ) *const Value; + + pub const buildFPToSI = LLVMBuildFPToSI; + extern fn LLVMBuildFPToSI( + *const Builder, + Val: *const Value, + DestTy: *const Type, + Name: [*:0]const u8, + ) *const Value; + + pub const buildUIToFP = LLVMBuildUIToFP; + extern fn LLVMBuildUIToFP( + *const Builder, + Val: *const Value, + DestTy: *const Type, + Name: [*:0]const u8, + ) *const Value; + + pub const buildSIToFP = LLVMBuildSIToFP; + extern fn LLVMBuildSIToFP( + *const Builder, + Val: *const Value, + DestTy: *const Type, + Name: [*:0]const u8, + ) *const Value; }; pub const IntPredicate = enum(c_uint) { |
