authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-17 00:24:23+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-23 11:55:00+02:00
logab7fc33c8342583a8323c19a2596b7e4cd0c5e90
treed76ac2acf85ea9aea83c5eff701bccc8295ea888
parent8bb1e0444951b7b83254277c52534c7ab58fd135
signature Commit is signed but in an unrecognized format.

add zig llvm wrapper for atomicrmw


4 files changed, 88 insertions(+), 17 deletions(-)

src/codegen.cpp+14-13
...@@ -5129,21 +5129,21 @@ static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {...@@ -5129,21 +5129,21 @@ static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
5129 zig_unreachable();5129 zig_unreachable();
5130}5130}
51315131
5132static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed, bool is_float) {5132static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed, bool is_float) {
5133 switch (op) {5133 switch (op) {
5134 case AtomicRmwOp_xchg: return LLVMAtomicRMWBinOpXchg;5134 case AtomicRmwOp_xchg: return ZigLLVMAtomicRMWBinOpXchg;
5135 case AtomicRmwOp_add:5135 case AtomicRmwOp_add:
5136 return is_float ? LLVMAtomicRMWBinOpFAdd: LLVMAtomicRMWBinOpAdd;5136 return is_float ? ZigLLVMAtomicRMWBinOpFAdd : ZigLLVMAtomicRMWBinOpAdd;
5137 case AtomicRmwOp_sub:5137 case AtomicRmwOp_sub:
5138 return is_float ? LLVMAtomicRMWBinOpFSub: LLVMAtomicRMWBinOpSub;5138 return is_float ? ZigLLVMAtomicRMWBinOpFSub : ZigLLVMAtomicRMWBinOpSub;
5139 case AtomicRmwOp_and: return LLVMAtomicRMWBinOpAnd;5139 case AtomicRmwOp_and: return ZigLLVMAtomicRMWBinOpAnd;
5140 case AtomicRmwOp_nand: return LLVMAtomicRMWBinOpNand;5140 case AtomicRmwOp_nand: return ZigLLVMAtomicRMWBinOpNand;
5141 case AtomicRmwOp_or: return LLVMAtomicRMWBinOpOr;5141 case AtomicRmwOp_or: return ZigLLVMAtomicRMWBinOpOr;
5142 case AtomicRmwOp_xor: return LLVMAtomicRMWBinOpXor;5142 case AtomicRmwOp_xor: return ZigLLVMAtomicRMWBinOpXor;
5143 case AtomicRmwOp_max:5143 case AtomicRmwOp_max:
5144 return is_signed ? LLVMAtomicRMWBinOpMax : LLVMAtomicRMWBinOpUMax;5144 return is_signed ? ZigLLVMAtomicRMWBinOpMax : ZigLLVMAtomicRMWBinOpUMax;
5145 case AtomicRmwOp_min:5145 case AtomicRmwOp_min:
5146 return is_signed ? LLVMAtomicRMWBinOpMin : LLVMAtomicRMWBinOpUMin;5146 return is_signed ? ZigLLVMAtomicRMWBinOpMin : ZigLLVMAtomicRMWBinOpUMin;
5147 }5147 }
5148 zig_unreachable();5148 zig_unreachable();
5149}5149}
...@@ -5727,6 +5727,7 @@ static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInst...@@ -5727,6 +5727,7 @@ static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInst
5727static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,5727static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
5728 IrInstructionAtomicRmw *instruction)5728 IrInstructionAtomicRmw *instruction)
5729{5729{
5730 bool is_signed;
5730 ZigType *operand_type = instruction->operand->value->type;5731 ZigType *operand_type = instruction->operand->value->type;
5731 bool is_float = operand_type->id == ZigTypeIdFloat;5732 bool is_float = operand_type->id == ZigTypeIdFloat;
5732 if (operand_type->id == ZigTypeIdInt) {5733 if (operand_type->id == ZigTypeIdInt) {
...@@ -5734,20 +5735,20 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,...@@ -5734,20 +5735,20 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
5734 } else {5735 } else {
5735 is_signed = false;5736 is_signed = false;
5736 }5737 }
5737 LLVMAtomicRMWBinOp op = to_LLVMAtomicRMWBinOp(instruction->resolved_op, is_signed, is_float);5738 enum ZigLLVM_AtomicRMWBinOp op = to_ZigLLVMAtomicRMWBinOp(instruction->resolved_op, is_signed, is_float);
5738 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering);5739 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering);
5739 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);5740 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
5740 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);5741 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
57415742
5742 if (get_codegen_ptr_type(operand_type) == nullptr) {5743 if (get_codegen_ptr_type(operand_type) == nullptr) {
5743 return LLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);5744 return ZigLLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, g->is_single_threaded);
5744 }5745 }
57455746
5746 // it's a pointer but we need to treat it as an int5747 // it's a pointer but we need to treat it as an int
5747 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,5748 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
5748 LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), "");5749 LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), "");
5749 LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->llvm_type, "");5750 LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->llvm_type, "");
5750 LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,5751 LLVMValueRef uncasted_result = ZigLLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering,
5751 g->is_single_threaded);5752 g->is_single_threaded);
5752 return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");5753 return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
5753}5754}
src/zig_llvm.cpp+50
...@@ -1096,6 +1096,56 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_...@@ -1096,6 +1096,56 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_
1096 abort();1096 abort();
1097}1097}
10981098
1099static AtomicRMWInst::BinOp toLLVMRMWBinOp(enum ZigLLVM_AtomicRMWBinOp BinOp) {
1100 switch (BinOp) {
1101 default:
1102 case ZigLLVMAtomicRMWBinOpXchg: return AtomicRMWInst::Xchg;
1103 case ZigLLVMAtomicRMWBinOpAdd: return AtomicRMWInst::Add;
1104 case ZigLLVMAtomicRMWBinOpSub: return AtomicRMWInst::Sub;
1105 case ZigLLVMAtomicRMWBinOpAnd: return AtomicRMWInst::And;
1106 case ZigLLVMAtomicRMWBinOpNand: return AtomicRMWInst::Nand;
1107 case ZigLLVMAtomicRMWBinOpOr: return AtomicRMWInst::Or;
1108 case ZigLLVMAtomicRMWBinOpXor: return AtomicRMWInst::Xor;
1109 case ZigLLVMAtomicRMWBinOpMax: return AtomicRMWInst::Max;
1110 case ZigLLVMAtomicRMWBinOpMin: return AtomicRMWInst::Min;
1111 case ZigLLVMAtomicRMWBinOpUMax: return AtomicRMWInst::UMax;
1112 case ZigLLVMAtomicRMWBinOpUMin: return AtomicRMWInst::UMin;
1113 case ZigLLVMAtomicRMWBinOpFAdd: return AtomicRMWInst::FAdd;
1114 case ZigLLVMAtomicRMWBinOpFSub: return AtomicRMWInst::FSub;
1115 }
1116}
1117
1118static AtomicOrdering toLLVMOrdering(LLVMAtomicOrdering Ordering) {
1119 switch (Ordering) {
1120 default:
1121 case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic;
1122 case LLVMAtomicOrderingUnordered: return AtomicOrdering::Unordered;
1123 case LLVMAtomicOrderingMonotonic: return AtomicOrdering::Monotonic;
1124 case LLVMAtomicOrderingAcquire: return AtomicOrdering::Acquire;
1125 case LLVMAtomicOrderingRelease: return AtomicOrdering::Release;
1126 case LLVMAtomicOrderingAcquireRelease: return AtomicOrdering::AcquireRelease;
1127 case LLVMAtomicOrderingSequentiallyConsistent: return AtomicOrdering::SequentiallyConsistent;
1128 }
1129}
1130
1131inline LLVMAttributeRef wrap(Attribute Attr) {
1132 return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
1133}
1134
1135inline Attribute unwrap(LLVMAttributeRef Attr) {
1136 return Attribute::fromRawPointer(Attr);
1137}
1138
1139LLVMValueRef ZigLLVMBuildAtomicRMW(LLVMBuilderRef B, enum ZigLLVM_AtomicRMWBinOp op,
1140 LLVMValueRef PTR, LLVMValueRef Val,
1141 LLVMAtomicOrdering ordering, LLVMBool singleThread)
1142{
1143 AtomicRMWInst::BinOp intop = toLLVMRMWBinOp(op);
1144 return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR),
1145 unwrap(Val), toLLVMOrdering(ordering),
1146 singleThread ? SyncScope::SingleThread : SyncScope::System));
1147}
1148
1099static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");1149static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");
1100static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, "");1150static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, "");
1101static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, "");1151static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, "");
src/zig_llvm.h+20
...@@ -422,6 +422,26 @@ enum ZigLLVM_ObjectFormatType {...@@ -422,6 +422,26 @@ enum ZigLLVM_ObjectFormatType {
422 ZigLLVM_XCOFF,422 ZigLLVM_XCOFF,
423};423};
424424
425enum ZigLLVM_AtomicRMWBinOp {
426 ZigLLVMAtomicRMWBinOpXchg,
427 ZigLLVMAtomicRMWBinOpAdd,
428 ZigLLVMAtomicRMWBinOpSub,
429 ZigLLVMAtomicRMWBinOpAnd,
430 ZigLLVMAtomicRMWBinOpNand,
431 ZigLLVMAtomicRMWBinOpOr,
432 ZigLLVMAtomicRMWBinOpXor,
433 ZigLLVMAtomicRMWBinOpMax,
434 ZigLLVMAtomicRMWBinOpMin,
435 ZigLLVMAtomicRMWBinOpUMax,
436 ZigLLVMAtomicRMWBinOpUMin,
437 ZigLLVMAtomicRMWBinOpFAdd,
438 ZigLLVMAtomicRMWBinOpFSub,
439};
440
441LLVMValueRef ZigLLVMBuildAtomicRMW(LLVMBuilderRef B, enum ZigLLVM_AtomicRMWBinOp op,
442 LLVMValueRef PTR, LLVMValueRef Val,
443 LLVMAtomicOrdering ordering, LLVMBool singleThread);
444
425#define ZigLLVM_DIFlags_Zero 0U445#define ZigLLVM_DIFlags_Zero 0U
426#define ZigLLVM_DIFlags_Private 1U446#define ZigLLVM_DIFlags_Private 1U
427#define ZigLLVM_DIFlags_Protected 2U447#define ZigLLVM_DIFlags_Protected 2U
test/compile_errors.zig+4-4
...@@ -19,9 +19,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -19,9 +19,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
19 \\ var x: f32 = 0;19 \\ var x: f32 = 0;
20 \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst);20 \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst);
21 \\}21 \\}
22 ,22 , &[_][]const u8{
23 "tmp.zig:3:22: error: expected integer, enum or pointer type, found 'f32'",23 "tmp.zig:3:22: error: expected integer, enum or pointer type, found 'f32'",
24 );24 });
2525
26 cases.add(26 cases.add(
27 "atomicrmw with float op not .Xchg, .Add or .Sub",27 "atomicrmw with float op not .Xchg, .Add or .Sub",
...@@ -29,9 +29,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -29,9 +29,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29 \\ var x: f32 = 0;29 \\ var x: f32 = 0;
30 \\ _ = @atomicRmw(f32, &x, .And, 2, .SeqCst);30 \\ _ = @atomicRmw(f32, &x, .And, 2, .SeqCst);
31 \\}31 \\}
32 ,32 , &[_][]const u8{
33 "tmp.zig:3:29: error: @atomicRmw with float only works with .Xchg, .Add and .Sub",33 "tmp.zig:3:29: error: @atomicRmw with float only works with .Xchg, .Add and .Sub",
34 );34 });
3535
36 cases.add("intToPtr with misaligned address",36 cases.add("intToPtr with misaligned address",
37 \\pub fn main() void {37 \\pub fn main() void {