aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhikari <ftphikari@gmail.com>2022-04-05 14:04:03 +0300
committerhikari <ftphikari@gmail.com>2022-04-05 14:04:03 +0300
commitef1fbbbce600af2705b7889f1807211bf60411fd (patch)
tree9499c22caec94b1f09b2e576fc98704ad76d098b /src
parent2a59aebe5b6460df77501703621e5efe55503f8b (diff)
parent59025b75ba885d0efb6475608a217083bfb1d63e (diff)
Merge branch 'master' of github.com:ftphikari/Odin
Diffstat (limited to 'src')
-rw-r--r--src/check_builtin.cpp107
-rw-r--r--src/checker_builtin_procs.hpp2
-rw-r--r--src/entity.cpp6
-rw-r--r--src/llvm_backend_proc.cpp2
-rw-r--r--src/main.cpp1
-rw-r--r--src/types.cpp11
6 files changed, 120 insertions, 9 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 8b8814176..e055539c5 100644
--- a/src/check_builtin.cpp
+++ b/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;
@@ -830,8 +831,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
}
} else if (name == "assert") {
- if (ce->args.count != 1) {
- error(call, "'#assert' expects 1 argument, got %td", ce->args.count);
+ if (ce->args.count != 1 && ce->args.count != 2) {
+ error(call, "'#assert' expects either 1 or 2 arguments, got %td", ce->args.count);
return false;
}
if (!is_type_boolean(operand->type) || operand->mode != Addressing_Constant) {
@@ -840,15 +841,37 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
gb_string_free(str);
return false;
}
+ if (ce->args.count == 2) {
+ Ast *arg = unparen_expr(ce->args[1]);
+ if (arg == nullptr || arg->kind != Ast_BasicLit || arg->BasicLit.token.kind != Token_String) {
+ gbString str = expr_to_string(arg);
+ error(call, "'%s' is not a constant string", str);
+ gb_string_free(str);
+ return false;
+ }
+ }
+
if (!operand->value.value_bool) {
- gbString arg = expr_to_string(ce->args[0]);
- error(call, "Compile time assertion: %s", arg);
+ gbString arg1 = expr_to_string(ce->args[0]);
+ gbString arg2 = {};
+
+ if (ce->args.count == 1) {
+ error(call, "Compile time assertion: %s", arg1);
+ } else {
+ arg2 = expr_to_string(ce->args[1]);
+ error(call, "Compile time assertion: %s (%s)", arg1, arg2);
+ }
+
if (c->proc_name != "") {
gbString str = type_to_string(c->curr_proc_sig);
error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str);
gb_string_free(str);
}
- gb_string_free(arg);
+
+ gb_string_free(arg1);
+ if (ce->args.count == 2) {
+ gb_string_free(arg2);
+ }
}
operand->type = t_untyped_bool;
@@ -3232,6 +3255,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:
@@ -3362,6 +3414,21 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
check_expr_with_type_hint(c, &x, ce->args[1], elem);
check_assignment(c, &x, elem, builtin_name);
+ Type *t = type_deref(operand->type);
+ switch (id) {
+ case BuiltinProc_atomic_add:
+ case BuiltinProc_atomic_sub:
+ if (!is_type_numeric(t)) {
+ gbString str = type_to_string(t);
+ error(operand->expr, "Expected a numeric type for '%.*s', got %s", LIT(builtin_name), str);
+ gb_string_free(str);
+ } else if (is_type_different_to_arch_endianness(t)) {
+ gbString str = type_to_string(t);
+ error(operand->expr, "Expected a numeric type of the same platform endianness for '%.*s', got %s", LIT(builtin_name), str);
+ gb_string_free(str);
+ }
+ }
+
operand->type = elem;
operand->mode = Addressing_Value;
break;
@@ -3389,6 +3456,22 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
return false;
}
+ Type *t = type_deref(operand->type);
+ switch (id) {
+ case BuiltinProc_atomic_add_explicit:
+ case BuiltinProc_atomic_sub_explicit:
+ if (!is_type_numeric(t)) {
+ gbString str = type_to_string(t);
+ error(operand->expr, "Expected a numeric type for '%.*s', got %s", LIT(builtin_name), str);
+ gb_string_free(str);
+ } else if (is_type_different_to_arch_endianness(t)) {
+ gbString str = type_to_string(t);
+ error(operand->expr, "Expected a numeric type of the same platform endianness for '%.*s', got %s", LIT(builtin_name), str);
+ gb_string_free(str);
+ }
+ break;
+ }
+
operand->type = elem;
operand->mode = Addressing_Value;
break;
@@ -3409,6 +3492,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
check_assignment(c, &x, elem, builtin_name);
check_assignment(c, &y, elem, builtin_name);
+ Type *t = type_deref(operand->type);
+ if (!is_type_comparable(t)) {
+ gbString str = type_to_string(t);
+ error(operand->expr, "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), str);
+ gb_string_free(str);
+ }
+
operand->mode = Addressing_OptionalOk;
operand->type = elem;
break;
@@ -3438,6 +3528,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
return false;
}
+ Type *t = type_deref(operand->type);
+ if (!is_type_comparable(t)) {
+ gbString str = type_to_string(t);
+ error(operand->expr, "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), str);
+ gb_string_free(str);
+ }
+
bool invalid_combination = false;
switch (success_memory_order) {
diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp
index c6b0afee0..fe14ae372 100644
--- a/src/checker_builtin_procs.hpp
+++ b/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},
diff --git a/src/entity.cpp b/src/entity.cpp
index 17fa884e1..1f87f7af6 100644
--- a/src/entity.cpp
+++ b/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,
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index 4de2af9d8..96ff19d10 100644
--- a/src/llvm_backend_proc.cpp
+++ b/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);
diff --git a/src/main.cpp b/src/main.cpp
index 9e470923d..52177e326 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2009,6 +2009,7 @@ void print_show_help(String const arg0, String const &command) {
print_usage_line(1, "-define:<name>=<expression>");
print_usage_line(2, "Defines a global constant with a value");
print_usage_line(2, "Example: -define:SPAM=123");
+ print_usage_line(2, "To use: #config(SPAM, default_value)");
print_usage_line(0, "");
}
diff --git a/src/types.cpp b/src/types.cpp
index e10dae1ed..b4dc17256 100644
--- a/src/types.cpp
+++ b/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);