Skip to content

Commit

Permalink
Fix atomic_fetch_sub builtin + Updated atomic library
Browse files Browse the repository at this point in the history
  • Loading branch information
OdnetninI committed Sep 16, 2023
1 parent ff05128 commit 375fd2f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 103 deletions.
130 changes: 28 additions & 102 deletions lib/std/atomic.c3
Original file line number Diff line number Diff line change
Expand Up @@ -85,31 +85,31 @@ macro Type Atomic.min(&self, Type value, AtomicOrdering ordering = SEQ_CONSISTEN
return @atomic_exec(atomic::fetch_min, data, value, ordering);
}

macro Type Atomic.or(&self, ulong value, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
macro Type Atomic.or(&self, uint value, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
{
Type* data = &self.data;
return @atomic_exec(atomic::fetch_or, data, value, ordering);
}

fn Type Atomic.xor(&self, ulong value, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
fn Type Atomic.xor(&self, uint value, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
{
Type* data = &self.data;
return @atomic_exec(atomic::fetch_xor, data, value, ordering);
}

macro Type Atomic.and(&self, ulong value, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
macro Type Atomic.and(&self, uint value, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
{
Type* data = &self.data;
return @atomic_exec(atomic::fetch_and, data, value, ordering);
}

macro Type Atomic.shift_right(&self, ulong amount, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
macro Type Atomic.shift_right(&self, uint amount, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
{
Type* data = &self.data;
return @atomic_exec(atomic::fetch_shift_right, data, amount, ordering);
}

macro Type Atomic.shift_left(&self, ulong amount, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
macro Type Atomic.shift_left(&self, uint amount, AtomicOrdering ordering = SEQ_CONSISTENT) @if(!types::is_float(Type))
{
Type* data = &self.data;
return @atomic_exec(atomic::fetch_shift_left, data, amount, ordering);
Expand Down Expand Up @@ -139,31 +139,9 @@ module std::atomic;
* @require types::is_int($typeof(*ptr)) || types::is_float($typeof(*ptr)) "Only integer/float pointers may be used."
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_add(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_add(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
$endif

var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));

$StorageType* storage_ptr = ($StorageType*)ptr;

$typeof(*ptr) old_value;
$typeof(*ptr) new_value;

$StorageType storage_old_value;
$StorageType storage_new_value;

do {
storage_old_value = $$atomic_load(storage_ptr, false, $load_ordering.ordinal);
old_value = bitcast(storage_old_value, $typeof(*ptr));
new_value = old_value + y;
storage_new_value = bitcast(new_value, $StorageType);
} while (mem::compare_exchange(storage_ptr, storage_old_value, storage_new_value, $ordering, $load_ordering) != storage_old_value);

return old_value;
return $$atomic_fetch_add(ptr, y, $volatile, $ordering.ordinal, $alignment);
}

/**
Expand All @@ -175,31 +153,9 @@ macro fetch_add(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
* @require types::is_int($typeof(*ptr)) || types::is_float($typeof(*ptr)) "Only integer/float pointers may be used."
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_sub(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_sub(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
$endif

var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));

$StorageType* storage_ptr = ($StorageType*)ptr;

$typeof(*ptr) old_value;
$typeof(*ptr) new_value;

$StorageType storage_old_value;
$StorageType storage_new_value;

do {
storage_old_value = $$atomic_load(storage_ptr, false, $load_ordering.ordinal);
old_value = bitcast(storage_old_value, $typeof(*ptr));
new_value = old_value - y;
storage_new_value = bitcast(new_value, $StorageType);
} while (mem::compare_exchange(storage_ptr, storage_old_value, storage_new_value, $ordering, $load_ordering) != storage_old_value);

return old_value;
return $$atomic_fetch_sub(ptr, y, $volatile, $ordering.ordinal, $alignment);
}

/**
Expand Down Expand Up @@ -285,8 +241,12 @@ macro fetch_div(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
* @require types::is_int($typeof(y)) "The value for or must be an int"
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_or(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_or(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
$if types::is_int($typeof(*ptr)):
return $$atomic_fetch_or(ptr, y, $volatile, $ordering.ordinal, $alignment);
$endif

var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
Expand Down Expand Up @@ -323,8 +283,12 @@ macro fetch_or(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
* @require types::is_int($typeof(y)) "The value for or must be an int"
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_xor(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_xor(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
$if types::is_int($typeof(*ptr)):
return $$atomic_fetch_xor(ptr, y, $volatile, $ordering.ordinal, $alignment);
$endif

var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
Expand Down Expand Up @@ -361,8 +325,12 @@ macro fetch_xor(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
* @require types::is_int($typeof(y)) "The value for or must be an int"
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_and(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_and(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
$if types::is_int($typeof(*ptr)):
return $$atomic_fetch_and(ptr, y, $volatile, $ordering.ordinal, $alignment);
$endif

var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
Expand Down Expand Up @@ -514,30 +482,9 @@ macro flag_clear(ptr, AtomicOrdering $ordering = SEQ_CONSISTENT)
* @require types::is_int($typeof(*ptr)) || types::is_float($typeof(*ptr)) "Only integer/float pointers may be used."
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_max(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_max(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
$endif

var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));

$StorageType* storage_ptr = ($StorageType*)ptr;

$typeof(*ptr) old_value;
$typeof(*ptr) new_value = y;

$StorageType storage_old_value;
$StorageType storage_new_value = bitcast(new_value, $StorageType);

do {
storage_old_value = $$atomic_load(storage_ptr, false, $load_ordering.ordinal);
old_value = bitcast(storage_old_value, $typeof(*ptr));
if (old_value >= new_value) break;
} while (mem::compare_exchange(storage_ptr, storage_old_value, storage_new_value, $ordering, $load_ordering) != storage_old_value);

return old_value;
return $$atomic_fetch_max(ptr, y, $volatile, $ordering.ordinal, $alignment);
}

/**
Expand All @@ -549,28 +496,7 @@ macro fetch_max(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
* @require types::is_int($typeof(*ptr)) || types::is_float($typeof(*ptr)) "Only integer/float pointers may be used."
* @require $ordering != AtomicOrdering.NOT_ATOMIC && $ordering != AtomicOrdering.UNORDERED "Acquire ordering is not valid."
**/
macro fetch_min(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
macro fetch_min(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT, bool $volatile = false, usz $alignment = 0)
{
var $load_ordering = $ordering;
$if $ordering == RELEASE || $ordering == ACQUIRE_RELEASE:
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
$endif

var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));

$StorageType* storage_ptr = ($StorageType*)ptr;

$typeof(*ptr) old_value;
$typeof(*ptr) new_value = y;

$StorageType storage_old_value;
$StorageType storage_new_value = bitcast(new_value, $StorageType);

do {
storage_old_value = $$atomic_load(storage_ptr, false, $load_ordering.ordinal);
old_value = bitcast(storage_old_value, $typeof(*ptr));
if (old_value <= new_value) break;
} while (mem::compare_exchange(storage_ptr, storage_old_value, storage_new_value, $ordering, $load_ordering) != storage_old_value);

return old_value;
return $$atomic_fetch_min(ptr, y, $volatile, $ordering.ordinal, $alignment);
}
2 changes: 1 addition & 1 deletion src/compiler/llvm_codegen_builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ INLINE void llvm_emit_atomic_fetch(GenContext *c, BuiltinFunction func, BEValue
op = is_float ? LLVMAtomicRMWBinOpFAdd : LLVMAtomicRMWBinOpAdd;
break;
case BUILTIN_ATOMIC_FETCH_SUB:
op = is_float ? LLVMAtomicRMWBinOpFAdd : LLVMAtomicRMWBinOpAdd;
op = is_float ? LLVMAtomicRMWBinOpFSub : LLVMAtomicRMWBinOpSub;
break;
case BUILTIN_ATOMIC_FETCH_MAX:
op = is_float ? LLVMAtomicRMWBinOpFMax : (is_unsigned ? LLVMAtomicRMWBinOpUMax : LLVMAtomicRMWBinOpMax);
Expand Down

0 comments on commit 375fd2f

Please sign in to comment.