diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-02-28 21:19:51 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-02-28 21:19:51 -0500 |
| commit | 807a5e94e976f03058426e04dceef449a5bf7ed8 (patch) | |
| tree | 3717696ae449bcc5c5a83ca4e1da965a63de864d /src/codegen.cpp | |
| parent | 36eadb569a31a87b610b9b70e225a981dc181df4 (diff) | |
| download | zig-807a5e94e976f03058426e04dceef449a5bf7ed8.tar.gz zig-807a5e94e976f03058426e04dceef449a5bf7ed8.zip | |
add atomicrmw builtin function
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index a5ae9996b5..89dc23f428 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3311,6 +3311,23 @@ static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { zig_unreachable(); } +static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed) { + switch (op) { + case AtomicRmwOp_xchg: return LLVMAtomicRMWBinOpXchg; + case AtomicRmwOp_add: return LLVMAtomicRMWBinOpAdd; + case AtomicRmwOp_sub: return LLVMAtomicRMWBinOpSub; + case AtomicRmwOp_and: return LLVMAtomicRMWBinOpAnd; + case AtomicRmwOp_nand: return LLVMAtomicRMWBinOpNand; + case AtomicRmwOp_or: return LLVMAtomicRMWBinOpOr; + case AtomicRmwOp_xor: return LLVMAtomicRMWBinOpXor; + case AtomicRmwOp_max: + return is_signed ? LLVMAtomicRMWBinOpMax : LLVMAtomicRMWBinOpUMax; + case AtomicRmwOp_min: + return is_signed ? LLVMAtomicRMWBinOpMin : LLVMAtomicRMWBinOpUMin; + } + zig_unreachable(); +} + static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) { LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); @@ -4111,6 +4128,22 @@ static LLVMValueRef ir_render_coro_alloc_helper(CodeGen *g, IrExecutable *execut get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); } +static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, + IrInstructionAtomicRmw *instruction) +{ + bool is_signed; + if (instruction->operand->value.type->id == TypeTableEntryIdInt) { + is_signed = instruction->operand->value.type->data.integral.is_signed; + } else { + is_signed = false; + } + LLVMAtomicRMWBinOp op = to_LLVMAtomicRMWBinOp(instruction->resolved_op, is_signed); + LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); + LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); + LLVMValueRef operand = ir_llvm_value(g, instruction->operand); + return LLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, false); +} + static void set_debug_location(CodeGen *g, IrInstruction *instruction) { AstNode *source_node = instruction->source_node; Scope *scope = instruction->scope; @@ -4318,6 +4351,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_coro_save(g, executable, (IrInstructionCoroSave *)instruction); case IrInstructionIdCoroAllocHelper: return ir_render_coro_alloc_helper(g, executable, (IrInstructionCoroAllocHelper *)instruction); + case IrInstructionIdAtomicRmw: + return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction); } zig_unreachable(); } @@ -5810,6 +5845,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); create_builtin_fn(g, BuiltinFnIdExport, "export", 3); create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0); + create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5); } static const char *bool_to_str(bool b) { @@ -5941,6 +5977,20 @@ static void define_builtin_compile_vars(CodeGen *g) { } { buf_appendf(contents, + "pub const AtomicRmwOp = enum {\n" + " Xchg,\n" + " Add,\n" + " Sub,\n" + " And,\n" + " Nand,\n" + " Or,\n" + " Xor,\n" + " Max,\n" + " Min,\n" + "};\n\n"); + } + { + buf_appendf(contents, "pub const Mode = enum {\n" " Debug,\n" " ReleaseSafe,\n" |
