authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-04 18:34:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-04 18:34:17-07:00
logdedde0d790a60522e073d78ce6bbb0714d50d7aa
tree4b5c8fe9440dcc8a8da7d8e5644874b9cb483007
parentc95e49785772a54916418630fbc7283791a4aa72

add fence builtin function


5 files changed, 58 insertions(+), 5 deletions(-)

src/all_types.hpp+2-1
...@@ -1116,6 +1116,7 @@ enum BuiltinFnId {...@@ -1116,6 +1116,7 @@ enum BuiltinFnId {
1116 BuiltinFnIdBreakpoint,1116 BuiltinFnIdBreakpoint,
1117 BuiltinFnIdEmbedFile,1117 BuiltinFnIdEmbedFile,
1118 BuiltinFnIdCmpExchange,1118 BuiltinFnIdCmpExchange,
1119 BuiltinFnIdFence,
1119};1120};
11201121
1121struct BuiltinFnEntry {1122struct BuiltinFnEntry {
...@@ -1184,7 +1185,7 @@ struct CodeGen {...@@ -1184,7 +1185,7 @@ struct CodeGen {
1184 TypeTableEntry *entry_os_enum;1185 TypeTableEntry *entry_os_enum;
1185 TypeTableEntry *entry_arch_enum;1186 TypeTableEntry *entry_arch_enum;
1186 TypeTableEntry *entry_environ_enum;1187 TypeTableEntry *entry_environ_enum;
1187 TypeTableEntry *entry_mem_order_enum;1188 TypeTableEntry *entry_atomic_order_enum;
1188 } builtin_types;1189 } builtin_types;
11891190
1190 ZigTarget zig_target;1191 ZigTarget zig_target;
src/analyze.cpp+29-2
...@@ -4417,6 +4417,8 @@ static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,...@@ -4417,6 +4417,8 @@ static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
4417static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,4417static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
4418 BlockContext *context, AstNode *node)4418 BlockContext *context, AstNode *node)
4419{4419{
4420 assert(node->type == NodeTypeFnCallExpr);
4421
4420 AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);4422 AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
4421 AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);4423 AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
4422 AstNode **new_arg = &node->data.fn_call_expr.params.at(2);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,9 +4439,9 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
4437 TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg);4439 TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg);
44384440
4439 TypeTableEntry *success_order_type = analyze_expression(g, import, context,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 TypeTableEntry *failure_order_type = analyze_expression(g, import, context,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);
44434445
4444 if (cmp_type->id == TypeTableEntryIdInvalid ||4446 if (cmp_type->id == TypeTableEntryIdInvalid ||
4445 new_type->id == TypeTableEntryIdInvalid ||4447 new_type->id == TypeTableEntryIdInvalid ||
...@@ -4485,6 +4487,29 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,...@@ -4485,6 +4487,29 @@ static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
4485 return g->builtin_types.entry_bool;4487 return g->builtin_types.entry_bool;
4486}4488}
44874489
4490static 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
4488static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4513static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4489 TypeTableEntry *expected_type, AstNode *node)4514 TypeTableEntry *expected_type, AstNode *node)
4490{4515{
...@@ -4823,6 +4848,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -4823,6 +4848,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
4823 return analyze_embed_file(g, import, context, node);4848 return analyze_embed_file(g, import, context, node);
4824 case BuiltinFnIdCmpExchange:4849 case BuiltinFnIdCmpExchange:
4825 return analyze_cmpxchg(g, import, context, node);4850 return analyze_cmpxchg(g, import, context, node);
4851 case BuiltinFnIdFence:
4852 return analyze_fence(g, import, context, node);
4826 }4853 }
4827 zig_unreachable();4854 zig_unreachable();
4828}4855}
src/codegen.cpp+18-2
...@@ -441,6 +441,20 @@ static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {...@@ -441,6 +441,20 @@ static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {
441 return LLVMBuildExtractValue(g->builder, result_val, 1, "");441 return LLVMBuildExtractValue(g->builder, result_val, 1, "");
442}442}
443443
444static 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
444static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {458static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
445 assert(node->type == NodeTypeFnCallExpr);459 assert(node->type == NodeTypeFnCallExpr);
446 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;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,6 +602,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
588 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");602 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
589 case BuiltinFnIdCmpExchange:603 case BuiltinFnIdCmpExchange:
590 return gen_cmp_exchange(g, node);604 return gen_cmp_exchange(g, node);
605 case BuiltinFnIdFence:
606 return gen_fence(g, node);
591 }607 }
592 zig_unreachable();608 zig_unreachable();
593}609}
...@@ -4139,7 +4155,7 @@ static void define_builtin_types(CodeGen *g) {...@@ -4139,7 +4155,7 @@ static void define_builtin_types(CodeGen *g) {
4139 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);4155 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
4140 entry->data.enumeration.tag_type = tag_type_entry;4156 entry->data.enumeration.tag_type = tag_type_entry;
41414157
4142 g->builtin_types.entry_mem_order_enum = entry;4158 g->builtin_types.entry_atomic_order_enum = entry;
4143 g->primitive_type_table.put(&entry->name, entry);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,7 +4257,7 @@ static void define_builtin_fns(CodeGen *g) {
4241 create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "err_name", 1);4257 create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "err_name", 1);
4242 create_builtin_fn_with_arg_count(g, BuiltinFnIdEmbedFile, "embed_file", 1);4258 create_builtin_fn_with_arg_count(g, BuiltinFnIdEmbedFile, "embed_file", 1);
4243 create_builtin_fn_with_arg_count(g, BuiltinFnIdCmpExchange, "cmpxchg", 5);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}
42464262
4247static void init(CodeGen *g, Buf *source_path) {4263static 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,6 +687,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
687 return eval_fn_with_overflow(ef, node, out_val, bignum_add);687 return eval_fn_with_overflow(ef, node, out_val, bignum_add);
688 case BuiltinFnIdSubWithOverflow:688 case BuiltinFnIdSubWithOverflow:
689 return eval_fn_with_overflow(ef, node, out_val, bignum_sub);689 return eval_fn_with_overflow(ef, node, out_val, bignum_sub);
690 case BuiltinFnIdFence:
691 return false;
690 case BuiltinFnIdMemcpy:692 case BuiltinFnIdMemcpy:
691 case BuiltinFnIdMemset:693 case BuiltinFnIdMemset:
692 case BuiltinFnIdSizeof:694 case BuiltinFnIdSizeof:
test/self_hosted.zig+7
...@@ -1449,3 +1449,10 @@ fn cmpxchg() {...@@ -1449,3 +1449,10 @@ fn cmpxchg() {
1449 while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}1449 while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
1450 assert(x == 5678);1450 assert(x == 5678);
1451}1451}
1452
1453#attribute("test")
1454fn fence() {
1455 var x: i32 = 1234;
1456 @fence(AtomicOrder.SeqCst);
1457 x = 5678;
1458}