From dedde0d790a60522e073d78ce6bbb0714d50d7aa Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 4 May 2016 18:34:17 -0700 Subject: [PATCH] add fence builtin function --- src/all_types.hpp | 3 ++- src/analyze.cpp | 31 +++++++++++++++++++++++++++++-- src/codegen.cpp | 20 ++++++++++++++++++-- src/eval.cpp | 2 ++ test/self_hosted.zig | 7 +++++++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 362b14707f..c07fc8f0fb 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1116,6 +1116,7 @@ enum BuiltinFnId { BuiltinFnIdBreakpoint, BuiltinFnIdEmbedFile, BuiltinFnIdCmpExchange, + BuiltinFnIdFence, }; struct BuiltinFnEntry { @@ -1184,7 +1185,7 @@ struct CodeGen { TypeTableEntry *entry_os_enum; TypeTableEntry *entry_arch_enum; TypeTableEntry *entry_environ_enum; - TypeTableEntry *entry_mem_order_enum; + TypeTableEntry *entry_atomic_order_enum; } builtin_types; ZigTarget zig_target; diff --git a/src/analyze.cpp b/src/analyze.cpp index 8039872deb..556c905e43 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4417,6 +4417,8 @@ static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) { + assert(node->type == NodeTypeFnCallExpr); + AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0); AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1); AstNode **new_arg = &node->data.fn_call_expr.params.at(2); @@ -4437,9 +4439,9 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg); TypeTableEntry *success_order_type = analyze_expression(g, import, context, - g->builtin_types.entry_mem_order_enum, *success_order_arg); + g->builtin_types.entry_atomic_order_enum, *success_order_arg); TypeTableEntry *failure_order_type = analyze_expression(g, import, context, - g->builtin_types.entry_mem_order_enum, *failure_order_arg); + g->builtin_types.entry_atomic_order_enum, *failure_order_arg); if (cmp_type->id == TypeTableEntryIdInvalid || new_type->id == TypeTableEntryIdInvalid || @@ -4485,6 +4487,29 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, return g->builtin_types.entry_bool; } +static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import, + BlockContext *context, AstNode *node) +{ + assert(node->type == NodeTypeFnCallExpr); + + AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0); + TypeTableEntry *atomic_order_type = analyze_expression(g, import, context, + g->builtin_types.entry_atomic_order_enum, *atomic_order_arg); + + if (atomic_order_type->id == TypeTableEntryIdInvalid) { + return g->builtin_types.entry_invalid; + } + + ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val; + + if (!atomic_order_val->ok) { + add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression")); + return g->builtin_types.entry_invalid; + } + + return g->builtin_types.entry_void; +} + static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) { @@ -4823,6 +4848,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry return analyze_embed_file(g, import, context, node); case BuiltinFnIdCmpExchange: return analyze_cmpxchg(g, import, context, node); + case BuiltinFnIdFence: + return analyze_fence(g, import, context, node); } zig_unreachable(); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 5f4cce5cad..a626ba7bfa 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -441,6 +441,20 @@ static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) { return LLVMBuildExtractValue(g->builder, result_val, 1, ""); } +static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) { + assert(node->type == NodeTypeFnCallExpr); + + AstNode *atomic_order_arg = node->data.fn_call_expr.params.at(0); + ConstExprValue *atomic_order_val = &get_resolved_expr(atomic_order_arg)->const_val; + + assert(atomic_order_val->ok); + + LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering((AtomicOrder)atomic_order_val->data.x_enum.tag); + + LLVMBuildFence(g->builder, atomic_order, false, ""); + return nullptr; +} + static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { assert(node->type == NodeTypeFnCallExpr); AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; @@ -588,6 +602,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, ""); case BuiltinFnIdCmpExchange: return gen_cmp_exchange(g, node); + case BuiltinFnIdFence: + return gen_fence(g, node); } zig_unreachable(); } @@ -4139,7 +4155,7 @@ static void define_builtin_types(CodeGen *g) { TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); entry->data.enumeration.tag_type = tag_type_entry; - g->builtin_types.entry_mem_order_enum = entry; + g->builtin_types.entry_atomic_order_enum = entry; g->primitive_type_table.put(&entry->name, entry); } } @@ -4241,7 +4257,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "err_name", 1); create_builtin_fn_with_arg_count(g, BuiltinFnIdEmbedFile, "embed_file", 1); create_builtin_fn_with_arg_count(g, BuiltinFnIdCmpExchange, "cmpxchg", 5); - //create_builtin_fn_with_arg_count(g, BuiltinFnIdAtomicRmw, "atomicrmw", 1); + create_builtin_fn_with_arg_count(g, BuiltinFnIdFence, "fence", 1); } static void init(CodeGen *g, Buf *source_path) { diff --git a/src/eval.cpp b/src/eval.cpp index eefa630b3d..1253125c56 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -687,6 +687,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_ return eval_fn_with_overflow(ef, node, out_val, bignum_add); case BuiltinFnIdSubWithOverflow: return eval_fn_with_overflow(ef, node, out_val, bignum_sub); + case BuiltinFnIdFence: + return false; case BuiltinFnIdMemcpy: case BuiltinFnIdMemset: case BuiltinFnIdSizeof: diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 3b85c09e90..23c0097bc2 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -1449,3 +1449,10 @@ fn cmpxchg() { while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} assert(x == 5678); } + +#attribute("test") +fn fence() { + var x: i32 = 1234; + @fence(AtomicOrder.SeqCst); + x = 5678; +}