| author | |
| committer | |
| log | ab7fc33c8342583a8323c19a2596b7e4cd0c5e90 |
| tree | d76ac2acf85ea9aea83c5eff701bccc8295ea888 |
| parent | 8bb1e0444951b7b83254277c52534c7ab58fd135 |
| signature | Commit is signed but in an unrecognized format. |
4 files changed, 88 insertions(+), 17 deletions(-)
src/codegen.cpp+14-13| ... | ... | @@ -5129,21 +5129,21 @@ static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { |
| 5129 | 5129 | zig_unreachable(); |
| 5130 | 5130 | } |
| 5131 | 5131 | |
| 5132 | static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed, bool is_float) { | |
| 5132 | static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed, bool is_float) { | |
| 5133 | 5133 | switch (op) { |
| 5134 | case AtomicRmwOp_xchg: return LLVMAtomicRMWBinOpXchg; | |
| 5134 | case AtomicRmwOp_xchg: return ZigLLVMAtomicRMWBinOpXchg; | |
| 5135 | 5135 | case AtomicRmwOp_add: |
| 5136 | return is_float ? LLVMAtomicRMWBinOpFAdd: LLVMAtomicRMWBinOpAdd; | |
| 5136 | return is_float ? ZigLLVMAtomicRMWBinOpFAdd : ZigLLVMAtomicRMWBinOpAdd; | |
| 5137 | 5137 | case AtomicRmwOp_sub: |
| 5138 | return is_float ? LLVMAtomicRMWBinOpFSub: LLVMAtomicRMWBinOpSub; | |
| 5139 | case AtomicRmwOp_and: return LLVMAtomicRMWBinOpAnd; | |
| 5140 | case AtomicRmwOp_nand: return LLVMAtomicRMWBinOpNand; | |
| 5141 | case AtomicRmwOp_or: return LLVMAtomicRMWBinOpOr; | |
| 5142 | case AtomicRmwOp_xor: return LLVMAtomicRMWBinOpXor; | |
| 5138 | return is_float ? ZigLLVMAtomicRMWBinOpFSub : ZigLLVMAtomicRMWBinOpSub; | |
| 5139 | case AtomicRmwOp_and: return ZigLLVMAtomicRMWBinOpAnd; | |
| 5140 | case AtomicRmwOp_nand: return ZigLLVMAtomicRMWBinOpNand; | |
| 5141 | case AtomicRmwOp_or: return ZigLLVMAtomicRMWBinOpOr; | |
| 5142 | case AtomicRmwOp_xor: return ZigLLVMAtomicRMWBinOpXor; | |
| 5143 | 5143 | case AtomicRmwOp_max: |
| 5144 | return is_signed ? LLVMAtomicRMWBinOpMax : LLVMAtomicRMWBinOpUMax; | |
| 5144 | return is_signed ? ZigLLVMAtomicRMWBinOpMax : ZigLLVMAtomicRMWBinOpUMax; | |
| 5145 | 5145 | case AtomicRmwOp_min: |
| 5146 | return is_signed ? LLVMAtomicRMWBinOpMin : LLVMAtomicRMWBinOpUMin; | |
| 5146 | return is_signed ? ZigLLVMAtomicRMWBinOpMin : ZigLLVMAtomicRMWBinOpUMin; | |
| 5147 | 5147 | } |
| 5148 | 5148 | zig_unreachable(); |
| 5149 | 5149 | } |
| ... | ... | @@ -5727,6 +5727,7 @@ static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInst |
| 5727 | 5727 | static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, |
| 5728 | 5728 | IrInstructionAtomicRmw *instruction) |
| 5729 | 5729 | { |
| 5730 | bool is_signed; | |
| 5730 | 5731 | ZigType *operand_type = instruction->operand->value->type; |
| 5731 | 5732 | bool is_float = operand_type->id == ZigTypeIdFloat; |
| 5732 | 5733 | if (operand_type->id == ZigTypeIdInt) { |
| ... | ... | @@ -5734,20 +5735,20 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, |
| 5734 | 5735 | } else { |
| 5735 | 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 | 5739 | LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); |
| 5739 | 5740 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 5740 | 5741 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); |
| 5741 | 5742 | |
| 5742 | 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 | } |
| 5745 | 5746 | |
| 5746 | 5747 | // it's a pointer but we need to treat it as an int |
| 5747 | 5748 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr, |
| 5748 | 5749 | LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), ""); |
| 5749 | 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 | 5752 | g->is_single_threaded); |
| 5752 | 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 | 1096 | abort(); |
| 1097 | 1097 | } |
| 1098 | 1098 | |
| 1099 | static 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 | ||
| 1118 | static 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 | ||
| 1131 | inline LLVMAttributeRef wrap(Attribute Attr) { | |
| 1132 | return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer()); | |
| 1133 | } | |
| 1134 | ||
| 1135 | inline Attribute unwrap(LLVMAttributeRef Attr) { | |
| 1136 | return Attribute::fromRawPointer(Attr); | |
| 1137 | } | |
| 1138 | ||
| 1139 | LLVMValueRef 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 | ||
| 1099 | 1149 | static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, ""); |
| 1100 | 1150 | static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, ""); |
| 1101 | 1151 | static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, ""); |
src/zig_llvm.h+20| ... | ... | @@ -422,6 +422,26 @@ enum ZigLLVM_ObjectFormatType { |
| 422 | 422 | ZigLLVM_XCOFF, |
| 423 | 423 | }; |
| 424 | 424 | |
| 425 | enum 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 | ||
| 441 | LLVMValueRef ZigLLVMBuildAtomicRMW(LLVMBuilderRef B, enum ZigLLVM_AtomicRMWBinOp op, | |
| 442 | LLVMValueRef PTR, LLVMValueRef Val, | |
| 443 | LLVMAtomicOrdering ordering, LLVMBool singleThread); | |
| 444 | ||
| 425 | 445 | #define ZigLLVM_DIFlags_Zero 0U |
| 426 | 446 | #define ZigLLVM_DIFlags_Private 1U |
| 427 | 447 | #define ZigLLVM_DIFlags_Protected 2U |
test/compile_errors.zig+4-4| ... | ... | @@ -19,9 +19,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 19 | 19 | \\ var x: f32 = 0; |
| 20 | 20 | \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst); |
| 21 | 21 | \\} |
| 22 | , | |
| 22 | , &[_][]const u8{ | |
| 23 | 23 | "tmp.zig:3:22: error: expected integer, enum or pointer type, found 'f32'", |
| 24 | ); | |
| 24 | }); | |
| 25 | 25 | |
| 26 | 26 | cases.add( |
| 27 | 27 | "atomicrmw with float op not .Xchg, .Add or .Sub", |
| ... | ... | @@ -29,9 +29,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 29 | 29 | \\ var x: f32 = 0; |
| 30 | 30 | \\ _ = @atomicRmw(f32, &x, .And, 2, .SeqCst); |
| 31 | 31 | \\} |
| 32 | , | |
| 32 | , &[_][]const u8{ | |
| 33 | 33 | "tmp.zig:3:29: error: @atomicRmw with float only works with .Xchg, .Add and .Sub", |
| 34 | ); | |
| 34 | }); | |
| 35 | 35 | |
| 36 | 36 | cases.add("intToPtr with misaligned address", |
| 37 | 37 | \\pub fn main() void { |