add fence builtin function
This commit is contained in:
parent
c95e497857
commit
dedde0d790
@ -1116,6 +1116,7 @@ enum BuiltinFnId {
|
|||||||
BuiltinFnIdBreakpoint,
|
BuiltinFnIdBreakpoint,
|
||||||
BuiltinFnIdEmbedFile,
|
BuiltinFnIdEmbedFile,
|
||||||
BuiltinFnIdCmpExchange,
|
BuiltinFnIdCmpExchange,
|
||||||
|
BuiltinFnIdFence,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuiltinFnEntry {
|
struct BuiltinFnEntry {
|
||||||
@ -1184,7 +1185,7 @@ struct CodeGen {
|
|||||||
TypeTableEntry *entry_os_enum;
|
TypeTableEntry *entry_os_enum;
|
||||||
TypeTableEntry *entry_arch_enum;
|
TypeTableEntry *entry_arch_enum;
|
||||||
TypeTableEntry *entry_environ_enum;
|
TypeTableEntry *entry_environ_enum;
|
||||||
TypeTableEntry *entry_mem_order_enum;
|
TypeTableEntry *entry_atomic_order_enum;
|
||||||
} builtin_types;
|
} builtin_types;
|
||||||
|
|
||||||
ZigTarget zig_target;
|
ZigTarget zig_target;
|
||||||
|
@ -4417,6 +4417,8 @@ static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
|
|||||||
static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
|
static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
|
||||||
BlockContext *context, AstNode *node)
|
BlockContext *context, AstNode *node)
|
||||||
{
|
{
|
||||||
|
assert(node->type == NodeTypeFnCallExpr);
|
||||||
|
|
||||||
AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
|
AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
|
||||||
AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
|
AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
|
||||||
AstNode **new_arg = &node->data.fn_call_expr.params.at(2);
|
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 *new_type = analyze_expression(g, import, context, child_type, *new_arg);
|
||||||
|
|
||||||
TypeTableEntry *success_order_type = analyze_expression(g, import, context,
|
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,
|
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 ||
|
if (cmp_type->id == TypeTableEntryIdInvalid ||
|
||||||
new_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;
|
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,
|
static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node)
|
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);
|
return analyze_embed_file(g, import, context, node);
|
||||||
case BuiltinFnIdCmpExchange:
|
case BuiltinFnIdCmpExchange:
|
||||||
return analyze_cmpxchg(g, import, context, node);
|
return analyze_cmpxchg(g, import, context, node);
|
||||||
|
case BuiltinFnIdFence:
|
||||||
|
return analyze_fence(g, import, context, node);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -441,6 +441,20 @@ static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {
|
|||||||
return LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
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) {
|
static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
||||||
assert(node->type == NodeTypeFnCallExpr);
|
assert(node->type == NodeTypeFnCallExpr);
|
||||||
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
|
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, "");
|
return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
|
||||||
case BuiltinFnIdCmpExchange:
|
case BuiltinFnIdCmpExchange:
|
||||||
return gen_cmp_exchange(g, node);
|
return gen_cmp_exchange(g, node);
|
||||||
|
case BuiltinFnIdFence:
|
||||||
|
return gen_fence(g, node);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
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);
|
TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
|
||||||
entry->data.enumeration.tag_type = tag_type_entry;
|
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);
|
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, BuiltinFnIdErrName, "err_name", 1);
|
||||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdEmbedFile, "embed_file", 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, 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) {
|
static void init(CodeGen *g, Buf *source_path) {
|
||||||
|
@ -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);
|
return eval_fn_with_overflow(ef, node, out_val, bignum_add);
|
||||||
case BuiltinFnIdSubWithOverflow:
|
case BuiltinFnIdSubWithOverflow:
|
||||||
return eval_fn_with_overflow(ef, node, out_val, bignum_sub);
|
return eval_fn_with_overflow(ef, node, out_val, bignum_sub);
|
||||||
|
case BuiltinFnIdFence:
|
||||||
|
return false;
|
||||||
case BuiltinFnIdMemcpy:
|
case BuiltinFnIdMemcpy:
|
||||||
case BuiltinFnIdMemset:
|
case BuiltinFnIdMemset:
|
||||||
case BuiltinFnIdSizeof:
|
case BuiltinFnIdSizeof:
|
||||||
|
@ -1449,3 +1449,10 @@ fn cmpxchg() {
|
|||||||
while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
|
while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
|
||||||
assert(x == 5678);
|
assert(x == 5678);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#attribute("test")
|
||||||
|
fn fence() {
|
||||||
|
var x: i32 = 1234;
|
||||||
|
@fence(AtomicOrder.SeqCst);
|
||||||
|
x = 5678;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user