| author | |
| committer | |
| log | dedde0d790a60522e073d78ce6bbb0714d50d7aa |
| tree | 4b5c8fe9440dcc8a8da7d8e5644874b9cb483007 |
| parent | c95e49785772a54916418630fbc7283791a4aa72 |
5 files changed, 58 insertions(+), 5 deletions(-)
src/all_types.hpp+2-1| ... | ... | @@ -1116,6 +1116,7 @@ enum BuiltinFnId { |
| 1116 | 1116 | BuiltinFnIdBreakpoint, |
| 1117 | 1117 | BuiltinFnIdEmbedFile, |
| 1118 | 1118 | BuiltinFnIdCmpExchange, |
| 1119 | BuiltinFnIdFence, | |
| 1119 | 1120 | }; |
| 1120 | 1121 | |
| 1121 | 1122 | struct BuiltinFnEntry { |
| ... | ... | @@ -1184,7 +1185,7 @@ struct CodeGen { |
| 1184 | 1185 | TypeTableEntry *entry_os_enum; |
| 1185 | 1186 | TypeTableEntry *entry_arch_enum; |
| 1186 | 1187 | TypeTableEntry *entry_environ_enum; |
| 1187 | TypeTableEntry *entry_mem_order_enum; | |
| 1188 | TypeTableEntry *entry_atomic_order_enum; | |
| 1188 | 1189 | } builtin_types; |
| 1189 | 1190 | |
| 1190 | 1191 | ZigTarget zig_target; |
src/analyze.cpp+29-2| ... | ... | @@ -4417,6 +4417,8 @@ static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, |
| 4417 | 4417 | static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, |
| 4418 | 4418 | BlockContext *context, AstNode *node) |
| 4419 | 4419 | { |
| 4420 | assert(node->type == NodeTypeFnCallExpr); | |
| 4421 | ||
| 4420 | 4422 | AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0); |
| 4421 | 4423 | AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1); |
| 4422 | 4424 | AstNode **new_arg = &node->data.fn_call_expr.params.at(2); |
| ... | ... | @@ -4437,9 +4439,9 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, |
| 4437 | 4439 | TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg); |
| 4438 | 4440 | |
| 4439 | 4441 | TypeTableEntry *success_order_type = analyze_expression(g, import, context, |
| 4440 | g->builtin_types.entry_mem_order_enum, *success_order_arg); | |
| 4442 | g->builtin_types.entry_atomic_order_enum, *success_order_arg); | |
| 4441 | 4443 | TypeTableEntry *failure_order_type = analyze_expression(g, import, context, |
| 4442 | g->builtin_types.entry_mem_order_enum, *failure_order_arg); | |
| 4444 | g->builtin_types.entry_atomic_order_enum, *failure_order_arg); | |
| 4443 | 4445 | |
| 4444 | 4446 | if (cmp_type->id == TypeTableEntryIdInvalid || |
| 4445 | 4447 | new_type->id == TypeTableEntryIdInvalid || |
| ... | ... | @@ -4485,6 +4487,29 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, |
| 4485 | 4487 | return g->builtin_types.entry_bool; |
| 4486 | 4488 | } |
| 4487 | 4489 | |
| 4490 | static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import, | |
| 4491 | BlockContext *context, AstNode *node) | |
| 4492 | { | |
| 4493 | assert(node->type == NodeTypeFnCallExpr); | |
| 4494 | ||
| 4495 | AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0); | |
| 4496 | TypeTableEntry *atomic_order_type = analyze_expression(g, import, context, | |
| 4497 | g->builtin_types.entry_atomic_order_enum, *atomic_order_arg); | |
| 4498 | ||
| 4499 | if (atomic_order_type->id == TypeTableEntryIdInvalid) { | |
| 4500 | return g->builtin_types.entry_invalid; | |
| 4501 | } | |
| 4502 | ||
| 4503 | ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val; | |
| 4504 | ||
| 4505 | if (!atomic_order_val->ok) { | |
| 4506 | add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression")); | |
| 4507 | return g->builtin_types.entry_invalid; | |
| 4508 | } | |
| 4509 | ||
| 4510 | return g->builtin_types.entry_void; | |
| 4511 | } | |
| 4512 | ||
| 4488 | 4513 | static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 4489 | 4514 | TypeTableEntry *expected_type, AstNode *node) |
| 4490 | 4515 | { |
| ... | ... | @@ -4823,6 +4848,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 4823 | 4848 | return analyze_embed_file(g, import, context, node); |
| 4824 | 4849 | case BuiltinFnIdCmpExchange: |
| 4825 | 4850 | return analyze_cmpxchg(g, import, context, node); |
| 4851 | case BuiltinFnIdFence: | |
| 4852 | return analyze_fence(g, import, context, node); | |
| 4826 | 4853 | } |
| 4827 | 4854 | zig_unreachable(); |
| 4828 | 4855 | } |
src/codegen.cpp+18-2| ... | ... | @@ -441,6 +441,20 @@ static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) { |
| 441 | 441 | return LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) { | |
| 445 | assert(node->type == NodeTypeFnCallExpr); | |
| 446 | ||
| 447 | AstNode *atomic_order_arg = node->data.fn_call_expr.params.at(0); | |
| 448 | ConstExprValue *atomic_order_val = &get_resolved_expr(atomic_order_arg)->const_val; | |
| 449 | ||
| 450 | assert(atomic_order_val->ok); | |
| 451 | ||
| 452 | LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering((AtomicOrder)atomic_order_val->data.x_enum.tag); | |
| 453 | ||
| 454 | LLVMBuildFence(g->builder, atomic_order, false, ""); | |
| 455 | return nullptr; | |
| 456 | } | |
| 457 | ||
| 444 | 458 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 445 | 459 | assert(node->type == NodeTypeFnCallExpr); |
| 446 | 460 | 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) { |
| 588 | 602 | return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, ""); |
| 589 | 603 | case BuiltinFnIdCmpExchange: |
| 590 | 604 | return gen_cmp_exchange(g, node); |
| 605 | case BuiltinFnIdFence: | |
| 606 | return gen_fence(g, node); | |
| 591 | 607 | } |
| 592 | 608 | zig_unreachable(); |
| 593 | 609 | } |
| ... | ... | @@ -4139,7 +4155,7 @@ static void define_builtin_types(CodeGen *g) { |
| 4139 | 4155 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); |
| 4140 | 4156 | entry->data.enumeration.tag_type = tag_type_entry; |
| 4141 | 4157 | |
| 4142 | g->builtin_types.entry_mem_order_enum = entry; | |
| 4158 | g->builtin_types.entry_atomic_order_enum = entry; | |
| 4143 | 4159 | g->primitive_type_table.put(&entry->name, entry); |
| 4144 | 4160 | } |
| 4145 | 4161 | } |
| ... | ... | @@ -4241,7 +4257,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4241 | 4257 | create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "err_name", 1); |
| 4242 | 4258 | create_builtin_fn_with_arg_count(g, BuiltinFnIdEmbedFile, "embed_file", 1); |
| 4243 | 4259 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCmpExchange, "cmpxchg", 5); |
| 4244 | //create_builtin_fn_with_arg_count(g, BuiltinFnIdAtomicRmw, "atomicrmw", 1); | |
| 4260 | create_builtin_fn_with_arg_count(g, BuiltinFnIdFence, "fence", 1); | |
| 4245 | 4261 | } |
| 4246 | 4262 | |
| 4247 | 4263 | static void init(CodeGen *g, Buf *source_path) { |
src/eval.cpp+2| ... | ... | @@ -687,6 +687,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_ |
| 687 | 687 | return eval_fn_with_overflow(ef, node, out_val, bignum_add); |
| 688 | 688 | case BuiltinFnIdSubWithOverflow: |
| 689 | 689 | return eval_fn_with_overflow(ef, node, out_val, bignum_sub); |
| 690 | case BuiltinFnIdFence: | |
| 691 | return false; | |
| 690 | 692 | case BuiltinFnIdMemcpy: |
| 691 | 693 | case BuiltinFnIdMemset: |
| 692 | 694 | case BuiltinFnIdSizeof: |
test/self_hosted.zig+7| ... | ... | @@ -1449,3 +1449,10 @@ fn cmpxchg() { |
| 1449 | 1449 | while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} |
| 1450 | 1450 | assert(x == 5678); |
| 1451 | 1451 | } |
| 1452 | ||
| 1453 | #attribute("test") | |
| 1454 | fn fence() { | |
| 1455 | var x: i32 = 1234; | |
| 1456 | @fence(AtomicOrder.SeqCst); | |
| 1457 | x = 5678; | |
| 1458 | } |