Browse Source

`intrinsics.atomic_type_is_lock_free`

gingerBill 3 years ago
parent
commit
a232c0888c

+ 1 - 1
core/c/libc/stdatomic.odin

@@ -70,7 +70,7 @@ atomic_signal_fence :: #force_inline proc(order: memory_order) {
 
 // 7.17.5 Lock-free property
 atomic_is_lock_free :: #force_inline proc(obj: ^$T) -> bool {
-	return size_of(T) <= 8 && (intrinsics.type_is_integer(T) || intrinsics.type_is_pointer(T))
+	return intrinsics.atomic_type_is_lock_free(T)
 }
 
 // 7.17.6 Atomic integer types

+ 2 - 0
core/intrinsics/intrinsics.odin

@@ -71,6 +71,8 @@ Atomic_Memory_Order :: enum {
 	Seq_Cst = 5,
 }
 
+atomic_type_is_lock_free :: proc($T: typeid) -> bool ---
+
 atomic_thread_fence :: proc(order: Atomic_Memory_Order) ---
 atomic_signal_fence :: proc(order: Atomic_Memory_Order) ---
 

+ 30 - 0
src/check_builtin.cpp

@@ -449,6 +449,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 	case BuiltinProc_objc_find_class: 
 	case BuiltinProc_objc_register_selector: 
 	case BuiltinProc_objc_register_class: 
+	case BuiltinProc_atomic_type_is_lock_free:
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		break;
 
@@ -3232,6 +3233,35 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 		break;
 
 
+	case BuiltinProc_atomic_type_is_lock_free:
+		{
+			Ast *expr = ce->args[0];
+			Operand o = {};
+			check_expr_or_type(c, &o, expr);
+
+			if (o.mode == Addressing_Invalid || o.mode == Addressing_Builtin) {
+				return false;
+			}
+			if (o.type == nullptr || o.type == t_invalid || is_type_asm_proc(o.type)) {
+				error(o.expr, "Invalid argument to '%.*s'", LIT(builtin_name));
+				return false;
+			}
+			if (is_type_polymorphic(o.type)) {
+				error(o.expr, "'%.*s' of polymorphic type cannot be determined", LIT(builtin_name));
+				return false;
+			}
+			if (is_type_untyped(o.type)) {
+				error(o.expr, "'%.*s' of untyped type is not allowed", LIT(builtin_name));
+				return false;
+			}
+			Type *t = o.type;
+			bool is_lock_free = is_type_lock_free(t);
+
+			operand->mode = Addressing_Constant;
+			operand->type = t_untyped_bool;
+			operand->value = exact_value_bool(is_lock_free);
+			break;
+		}
 
 	case BuiltinProc_atomic_thread_fence:
 	case BuiltinProc_atomic_signal_fence:

+ 2 - 0
src/checker_builtin_procs.hpp

@@ -86,6 +86,7 @@ enum BuiltinProcId {
 	BuiltinProc_prefetch_write_instruction,
 	BuiltinProc_prefetch_write_data,
 
+	BuiltinProc_atomic_type_is_lock_free,
 	BuiltinProc_atomic_thread_fence,
 	BuiltinProc_atomic_signal_fence,
 	BuiltinProc_atomic_store,
@@ -305,6 +306,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("prefetch_write_instruction"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
 	{STR_LIT("prefetch_write_data"),        2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
 
+	{STR_LIT("atomic_type_is_lock_free"),                1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("atomic_thread_fence"),                     1, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
 	{STR_LIT("atomic_signal_fence"),                     1, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
 	{STR_LIT("atomic_store"),                            2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},

+ 3 - 3
src/entity.cpp

@@ -45,9 +45,9 @@ enum EntityFlag : u64 {
 	EntityFlag_NoAlias       = 1ull<<9,
 	EntityFlag_TypeField     = 1ull<<10,
 	EntityFlag_Value         = 1ull<<11,
-	EntityFlag_Sret          = 1ull<<12,
-	EntityFlag_ByVal         = 1ull<<13,
-	EntityFlag_BitFieldValue = 1ull<<14,
+
+
+
 	EntityFlag_PolyConst     = 1ull<<15,
 	EntityFlag_NotExported   = 1ull<<16,
 	EntityFlag_ConstInput    = 1ull<<17,

+ 1 - 1
src/llvm_backend_proc.cpp

@@ -447,7 +447,7 @@ void lb_begin_procedure_body(lbProcedure *p) {
 
 			Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(p->type->Proc.results));
 			Entity *e = alloc_entity_param(nullptr, make_token_ident(name), ptr_type, false, false);
-			e->flags |= EntityFlag_Sret | EntityFlag_NoAlias;
+			e->flags |= EntityFlag_NoAlias;
 
 			return_ptr_value.value = LLVMGetParam(p->value, 0);
 			LLVMSetValueName2(return_ptr_value.value, cast(char const *)name.text, name.len);

+ 11 - 0
src/types.cpp

@@ -2218,6 +2218,17 @@ bool elem_type_can_be_constant(Type *t) {
 	return true;
 }
 
+bool is_type_lock_free(Type *t) {
+	t = core_type(t);
+	if (t == t_invalid) {
+		return false;
+	}
+	i64 sz = type_size_of(t);
+	// TODO(bill): Figure this out correctly
+	return sz <= build_context.max_align;
+}
+
+
 
 bool is_type_comparable(Type *t) {
 	t = base_type(t);