Skip to content

Commit

Permalink
Fixes missing checks to body arguments. Do not create debug declarati…
Browse files Browse the repository at this point in the history
…on for value-only parameter. Bug in alignment for atomics. Macro ref parameters are pointers.
  • Loading branch information
lerno committed Jul 15, 2023
1 parent ab32e0d commit 1f9838f
Show file tree
Hide file tree
Showing 55 changed files with 1,454 additions and 1,504 deletions.
7 changes: 4 additions & 3 deletions lib/std/core/builtin.c3
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ macro void @scope(&variable; @body) @builtin

/**
* Swap two variables
* @checked *a = *b, *b = *a
**/
macro void @swap(&a, &b) @builtin
{
var temp = a;
a = b;
b = temp;
var temp = *a;
*a = *b;
*b = temp;
}

/**
Expand Down
12 changes: 8 additions & 4 deletions lib/std/core/mem.c3
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ const DEFAULT_MEM_ALIGNMENT = (void*.alignof) * 2;

macro @volatile_load(&x) @builtin
{
return $$volatile_load(&x);
return $$volatile_load(x);
}

/**
* @checked *x == y : "The value doesn't match the variable"
**/
macro @volatile_store(&x, y) @builtin
{
return $$volatile_store(&x, ($typeof(x))y);
return $$volatile_store(x, ($typeof(*x))y);
}

enum AtomicOrdering : int
Expand All @@ -37,10 +40,11 @@ enum AtomicOrdering : int
* @require $ordering != AtomicOrdering.RELEASE "Release ordering is not valid for load."
* @require $ordering != AtomicOrdering.ACQUIRE_RELEASE "Acquire release is not valid for load."
* @require types::may_load_atomic($typeof(x)) "Only integer, float and pointers may be used."
* @require @typekind(x) == POINTER "You can only load from a pointer"
**/
macro @atomic_load(&x, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = false) @builtin
{
return $$atomic_load(&x, $volatile, (int)$ordering);
return $$atomic_load(x, $volatile, (int)$ordering);
}

/**
Expand All @@ -55,7 +59,7 @@ macro @atomic_load(&x, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = fa
**/
macro void @atomic_store(&x, value, AtomicOrdering $ordering = SEQ_CONSISTENT, $volatile = false) @builtin
{
$$atomic_store(&x, value, $volatile, (int)$ordering);
$$atomic_store(x, value, $volatile, (int)$ordering);
}

macro compare_exchange(ptr, compare, value, AtomicOrdering $success = SEQ_CONSISTENT, AtomicOrdering $failure = SEQ_CONSISTENT, bool $volatile = true, bool $weak = false, usz $alignment = 0)
Expand Down
20 changes: 10 additions & 10 deletions lib/std/core/mem_allocator.c3
Original file line number Diff line number Diff line change
Expand Up @@ -64,62 +64,62 @@ fault AllocationFailure

macro void*! Allocator.alloc(&allocator, usz size)
{
return allocator.function(&allocator, size, 0, 0, null, ALLOC);
return allocator.function(allocator, size, 0, 0, null, ALLOC);
}

/**
* @require alignment && math::is_power_of_2(alignment)
*/
macro void*! Allocator.alloc_aligned(&allocator, usz size, usz alignment, usz offset = 0)
{
return allocator.function(&allocator, size, alignment, offset, null, ALIGNED_ALLOC);
return allocator.function(allocator, size, alignment, offset, null, ALIGNED_ALLOC);
}

macro void*! Allocator.realloc(&allocator, void* old_pointer, usz size)
{
return allocator.function(&allocator, size, 0, 0, old_pointer, REALLOC);
return allocator.function(allocator, size, 0, 0, old_pointer, REALLOC);
}

/**
* @require alignment && math::is_power_of_2(alignment)
*/
macro void*! Allocator.realloc_aligned(&allocator, void* old_pointer, usz size, usz alignment, usz offset = 0)
{
return allocator.function(&allocator, size, alignment, offset, old_pointer, ALIGNED_REALLOC);
return allocator.function(allocator, size, alignment, offset, old_pointer, ALIGNED_REALLOC);
}

macro usz Allocator.mark(&allocator)
{
return (usz)(uptr)allocator.function(&allocator, 0, 0, 0, null, MARK) ?? 0;
return (usz)(uptr)allocator.function(allocator, 0, 0, 0, null, MARK) ?? 0;
}


macro void*! Allocator.calloc(&allocator, usz size)
{
return allocator.function(&allocator, size, 0, 0, null, CALLOC);
return allocator.function(allocator, size, 0, 0, null, CALLOC);
}

/**
* @require alignment && math::is_power_of_2(alignment)
*/
macro void*! Allocator.calloc_aligned(&allocator, usz size, usz alignment, usz offset = 0)
{
return allocator.function(&allocator, size, alignment, offset, null, ALIGNED_CALLOC);
return allocator.function(allocator, size, alignment, offset, null, ALIGNED_CALLOC);
}

macro void! Allocator.free(&allocator, void* old_pointer)
{
allocator.function(&allocator, 0, 0, 0, old_pointer, FREE)!;
allocator.function(allocator, 0, 0, 0, old_pointer, FREE)!;
}

macro void! Allocator.free_aligned(&allocator, void* old_pointer)
{
allocator.function(&allocator, 0, 0, 0, old_pointer, ALIGNED_FREE)!;
allocator.function(allocator, 0, 0, 0, old_pointer, ALIGNED_FREE)!;
}

macro void Allocator.reset(&allocator, usz mark = 0)
{
(void)allocator.function(&allocator, mark, 0, 0, null, RESET);
(void)allocator.function(allocator, mark, 0, 0, null, RESET);
}

fn usz alignment_for_allocation(usz alignment) @inline @private
Expand Down
2 changes: 1 addition & 1 deletion lib/std/hash/fnv32a.c3
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def Fnv32a = distinct uint;
const FNV32A_START @private = 0x811c9dc5;
const FNV32A_MUL @private = 0x01000193;

macro void @update(uint &h, char x) @private => h = (h * FNV32A_MUL) ^ x;
macro void @update(uint* &h, char x) @private => *h = (*h * FNV32A_MUL) ^ x;

fn void Fnv32a.init(&self)
{
Expand Down
2 changes: 1 addition & 1 deletion lib/std/hash/fnv64a.c3
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def Fnv64a = distinct ulong;
const FNV64A_START @private = 0xcbf29ce484222325;
const FNV64A_MUL @private = 0x00000100000001b3;

macro void @update(ulong &h, char x) @private => h = (h * FNV64A_MUL) ^ x;
macro void @update(ulong* &h, char x) @private => *h = (*h * FNV64A_MUL) ^ x;

fn void Fnv64a.init(&self)
{
Expand Down
35 changes: 20 additions & 15 deletions lib/std/hash/sha1.c3
Original file line number Diff line number Diff line change
Expand Up @@ -103,34 +103,39 @@ macro @blk0(&block, i) @local
$endif
}

macro @r0(&block, v, &w, x, y, &z, i) @local
macro @r0(&block, v, &wref, x, y, &z, i) @local
{
z += ((w & (x ^ y)) ^ y) + @blk0(block, i) + 0x5A827999 + v.rotl(5);
w = w.rotl(30);
var w = *wref;
*z += ((w & (x ^ y)) ^ y) + @blk0(*block, i) + 0x5A827999 + v.rotl(5);
*wref = w.rotl(30);
}

macro @r1(&block, v, &w, x, y, &z, i) @local
macro @r1(&block, v, &wref, x, y, &z, i) @local
{
z += ((w & (x ^ y)) ^ y) + @blk(block, i) + 0x5A827999 + v.rotl(5);
w = w.rotl(30);
var w = *wref;
*z += ((w & (x ^ y)) ^ y) + @blk(*block, i) + 0x5A827999 + v.rotl(5);
*wref = w.rotl(30);
}

macro @r2(&block, v, &w, x, y, &z, i) @local
macro @r2(&block, v, &wref, x, y, &z, i) @local
{
z += (w ^ x ^ y) + @blk(block, i) + 0x6ED9EBA1 + v.rotl(5);
w = w.rotl(30);
var w = *wref;
*z += (w ^ x ^ y) + @blk(*block, i) + 0x6ED9EBA1 + v.rotl(5);
*wref = w.rotl(30);
}

macro @r3(&block, v, &w, x, y, &z, i) @local
macro @r3(&block, v, &wref, x, y, &z, i) @local
{
z += (((w | x) &y) | (w & x)) + @blk(block, i) + 0x8F1BBCDC + v.rotl(5);
w = w.rotl(30);
var w = *wref;
*z += (((w | x) & y) | (w & x)) + @blk(*block, i) + 0x8F1BBCDC + v.rotl(5);
*wref = w.rotl(30);
}

macro @r4(&block, v, &w, x, y, &z, i) @local
macro @r4(&block, v, &wref, x, y, &z, i) @local
{
z += (w ^ x ^ y) + @blk(block, i) + 0xCA62C1D6 + v.rotl(5);
w = w.rotl(30);
var w = *wref;
*z += (w ^ x ^ y) + @blk(*block, i) + 0xCA62C1D6 + v.rotl(5);
*wref = w.rotl(30);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/std/io/io_printf.c3
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ macro bool! Formatter.print_with_function(&self, any arg)
self.width = old_width;
self.prec = old_prec;
}
arg.to_format(&self)!;
arg.to_format(self)!;
return true;
}
if (&arg.to_string)
Expand Down
8 changes: 4 additions & 4 deletions lib/std/math/math_vector.c3
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ def Vec2 = double[<2>];
def Vec3 = double[<3>];
def Vec4 = double[<4>];

macro Vec2f.length_sq(&self) => self.dot(self);
macro Vec3f.length_sq(&self) => self.dot(self);
macro Vec4f.length_sq(&self) => self.dot(self);
macro Vec2.length_sq(&self) => self.dot(self);
macro Vec2f.length_sq(self) => self.dot(self);
macro Vec3f.length_sq(self) => self.dot(self);
macro Vec4f.length_sq(self) => self.dot(self);
macro Vec2.length_sq(self) => self.dot(self);
macro Vec3.length_sq(self) => self.dot(self);
macro Vec4.length_sq(self) => self.dot(self);

Expand Down
5 changes: 5 additions & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Exhaustive switches with enums has better analysis.
- Globals may now be initialized with optional values.
- New generic syntax.
- Macro ref parameters are now of pointer type and ref parameters are not assignable.
- Added `nextcase default`.
- Added `$embed` to embed binary data.
- Ad hoc generics are now allowed.
Expand Down Expand Up @@ -46,6 +47,7 @@
- Addition of `@local` for file local visibility.
- Addition of `@public` for overriding default visibility.
- Default visibility can be overridden per module compile unit. Eg `module foo @private`.
- Optimized macro codegen for -O0.
- Addition of unary `+`.
- Remove the `:` and `;` used in $if, $switch etc.
- Faults have an ordinal.
Expand Down Expand Up @@ -144,6 +146,9 @@
- Added posix socket functions.
### Fixes
- Fixes missing checks to body arguments.
- Do not create debug declaration for value-only parameter.
- Bug in alignment for atomics.
- Fix to bug when comparing nested arrays.
- Fix to bug when a macro is using rethrow.
- Fixes bug initializing a const struct with a const struct value.
Expand Down
8 changes: 4 additions & 4 deletions resources/examples/swap.c3
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ module test;
import libc;

/**
* @checked a = b, b = a
* @checked *a = *b, *b = *a
*/
macro void @swap(&a, &b)
{
$typeof(a) temp = a;
a = b;
b = temp;
var temp = *a;
*a = *b;
*b = temp;
}

fn void main()
Expand Down
24 changes: 23 additions & 1 deletion src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,11 @@ typedef struct Decl_
void *tb_symbol;
};
AlignSize alignment;
const char *section;
union
{
const char *section;
ExprId varef_id;
};
AlignSize offset : 32;
AlignSize padding : 32;
/* bool is_exported : 1;
Expand Down Expand Up @@ -2974,6 +2978,24 @@ INLINE bool expr_is_deref(Expr *expr)
return expr->expr_kind == EXPR_UNARY && expr->unary_expr.operator == UNARYOP_DEREF;
}

INLINE bool expr_is_addr(Expr *expr)
{
return expr->expr_kind == EXPR_UNARY && expr->unary_expr.operator == UNARYOP_ADDR;
}

INLINE bool expr_is_any_addr(Expr *expr)
{
if (expr->expr_kind != EXPR_UNARY) return false;
switch (expr->unary_expr.operator)
{
case UNARYOP_ADDR:
case UNARYOP_TADDR:
return true;
default:
return false;
}
}

INLINE bool expr_is_mult(Expr *expr)
{
return expr->expr_kind == EXPR_BINARY && expr->binary_expr.operator == BINARYOP_MULT;
Expand Down
6 changes: 4 additions & 2 deletions src/compiler/llvm_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value)
switch (value->type->type_kind)
{
case TYPE_POINTER:
llvm_value_rvalue(c, value);
value->kind = BE_ADDRESS;
llvm_value_rvalue(c, value);
value->kind = BE_ADDRESS;
return;
case TYPE_ARRAY:
case TYPE_VECTOR:
Expand Down Expand Up @@ -585,6 +585,7 @@ void llvm_emit_and_set_decl_alloca(GenContext *c, Decl *decl)
{
Type *type = type_lowering(decl->type);
if (type == type_void) return;
assert(!decl->backend_ref && !decl->is_value);
decl->backend_ref = llvm_emit_alloca(c, llvm_get_type(c, type), decl->alignment, decl->name ? decl->name : ".anon");
}

Expand Down Expand Up @@ -1023,6 +1024,7 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl)
}
LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
{
assert(!decl->is_value);
LLVMValueRef backend_ref = decl->backend_ref;
if (backend_ref)
{
Expand Down
14 changes: 4 additions & 10 deletions src/compiler/llvm_codegen_builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ INLINE void llvm_emit_volatile_store(GenContext *c, BEValue *result_value, Expr
BEValue value;
llvm_emit_expr(c, &value, expr->call_expr.arguments[0]);
llvm_emit_expr(c, result_value, expr->call_expr.arguments[1]);
llvm_value_rvalue(c, &value);
value.kind = BE_ADDRESS;
llvm_value_deref(c, &value);
BEValue store_value = *result_value;
LLVMValueRef store = llvm_store(c, &value, &store_value);
if (store) LLVMSetVolatile(store, true);
Expand All @@ -150,9 +149,7 @@ INLINE void llvm_emit_volatile_store(GenContext *c, BEValue *result_value, Expr
INLINE void llvm_emit_volatile_load(GenContext *c, BEValue *result_value, Expr *expr)
{
llvm_emit_expr(c, result_value, expr->call_expr.arguments[0]);
llvm_value_rvalue(c, result_value);
result_value->kind = BE_ADDRESS;
result_value->type = type_lowering(result_value->type->pointer);
llvm_value_deref(c, result_value);
llvm_value_rvalue(c, result_value);
LLVMSetVolatile(result_value->value, true);
}
Expand All @@ -162,8 +159,7 @@ INLINE void llvm_emit_atomic_store(GenContext *c, BEValue *result_value, Expr *e
BEValue value;
llvm_emit_expr(c, &value, expr->call_expr.arguments[0]);
llvm_emit_expr(c, result_value, expr->call_expr.arguments[1]);
llvm_value_rvalue(c, &value);
value.kind = BE_ADDRESS;
llvm_value_deref(c, &value);
BEValue store_value = *result_value;
LLVMValueRef store = llvm_store(c, &value, &store_value);
if (store)
Expand All @@ -176,9 +172,7 @@ INLINE void llvm_emit_atomic_store(GenContext *c, BEValue *result_value, Expr *e
INLINE void llvm_emit_atomic_load(GenContext *c, BEValue *result_value, Expr *expr)
{
llvm_emit_expr(c, result_value, expr->call_expr.arguments[0]);
llvm_value_rvalue(c, result_value);
result_value->kind = BE_ADDRESS;
result_value->type = type_lowering(result_value->type->pointer);
llvm_value_deref(c, result_value);
llvm_value_rvalue(c, result_value);
if (expr->call_expr.arguments[1]->const_expr.b) LLVMSetVolatile(result_value->value, true);
LLVMSetOrdering(result_value->value, llvm_atomic_ordering(expr->call_expr.arguments[2]->const_expr.ixx.i.low));
Expand Down
Loading

0 comments on commit 1f9838f

Please sign in to comment.