aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-10-13 12:38:23 +0100
committergingerBill <bill@gingerbill.org>2019-10-13 12:38:23 +0100
commit2a6d9e8927ad1eb1e5f3a79fc9ed068a02cbfdfc (patch)
tree1e771afe3e07425e536b3519818306a6d4e022ff /src
parentfa81061db0d08a508ab8bbedfcf7bf5ad1e27daa (diff)
`#panic`; Minor change to demo.odin; Fix `#assert` bug at file scope
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp22
-rw-r--r--src/check_type.cpp37
-rw-r--r--src/checker.cpp13
-rw-r--r--src/checker.hpp1
-rw-r--r--src/main.cpp14
-rw-r--r--src/parser.cpp38
-rw-r--r--src/types.cpp66
7 files changed, 106 insertions, 85 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 6a0d8221f..7c418c4f0 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3071,7 +3071,6 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
}
if (selector->kind != Ast_Ident) {
- // if (selector->kind != Ast_Ident) {
error(selector, "Illegal selector kind: '%.*s'", LIT(ast_strings[selector->kind]));
operand->mode = Addressing_Invalid;
operand->expr = node;
@@ -3544,6 +3543,25 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
operand->type = t_untyped_bool;
operand->mode = Addressing_Constant;
+ } else if (name == "panic") {
+ if (ce->args.count != 1) {
+ error(call, "'#panic' expects 1 argument, got %td", ce->args.count);
+ return false;
+ }
+ if (!is_type_string(operand->type) && operand->mode != Addressing_Constant) {
+ gbString str = expr_to_string(ce->args[0]);
+ error(call, "'%s' is not a constant string", str);
+ gb_string_free(str);
+ return false;
+ }
+ error(call, "Compile time panic: %.*s", LIT(operand->value.value_string));
+ 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);
+ }
+ operand->type = t_invalid;
+ operand->mode = Addressing_NoValue;
} else if (name == "defined") {
if (ce->args.count != 1) {
error(call, "'#defined' expects 1 argument, got %td", ce->args.count);
@@ -6349,7 +6367,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call) {
ce->proc->kind == Ast_BasicDirective) {
ast_node(bd, BasicDirective, ce->proc);
String name = bd->name;
- if (name == "location" || name == "assert" || name == "defined" || name == "load") {
+ if (name == "location" || name == "assert" || name == "panic" || name == "defined" || name == "load") {
operand->mode = Addressing_Builtin;
operand->builtin_id = BuiltinProc_DIRECTIVE;
operand->expr = ce->proc;
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 329755ea5..4d107a9ac 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1847,7 +1847,7 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
}
auto distributed = array_make<Type *>(heap_allocator(), 0, distributed_cap);
-
+ i64 sz = type_size_of(bt);
switch (bt->kind) {
case Type_Basic:
switch (bt->Basic.kind){
@@ -1925,9 +1925,9 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
array_add(&distributed, t_int);
break;
+ case Type_Union:
case Type_DynamicArray:
case Type_Map:
- case Type_Union:
case Type_BitField: // TODO(bill): Ignore?
// NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet
goto DEFAULT;
@@ -1937,7 +1937,7 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
case Type_SimdVector: // TODO(bill): Is this correct logic?
default:
DEFAULT:;
- if (type_size_of(bt) > 0) {
+ if (sz > 0) {
array_add(&distributed, bt);
}
break;
@@ -1959,13 +1959,22 @@ Type *handle_single_distributed_type_parameter(Array<Type *> const &types, bool
if (types.count == 1) {
if (offset) *offset = 1;
+
+ i64 sz = type_size_of(types[0]);
+
if (is_type_float(types[0])) {
return types[0];
- } else if (type_size_of(types[0]) == 8) {
+ }
+ switch (sz) {
+ case 0:
+ GB_PANIC("Zero sized type found!");
+ case 1:
+ case 2:
+ case 4:
+ case 8:
return types[0];
- } else {
- return t_u64;
}
+ return t_u64;
} else if (types.count >= 2) {
if (types[0] == t_f32 && types[1] == t_f32) {
if (offset) *offset = 2;
@@ -2050,7 +2059,7 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) {
Type *final_type = nullptr;
if (field_types.count == 0) {
- return t;
+ final_type = t;
} else if (field_types.count == 1) {
final_type = field_types[0];
} else {
@@ -2072,8 +2081,22 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) {
variables[1] = alloc_entity_param(nullptr, empty_token, two_types[1], false, false);
final_type = alloc_type_tuple();
final_type->Tuple.variables = variables;
+ if (t->kind == Type_Struct) {
+ // NOTE(bill): Make this packed
+ final_type->Tuple.is_packed = t->Struct.is_packed;
+ }
}
}
+
+
+ GB_ASSERT(final_type != nullptr);
+ i64 ftsz = type_size_of(final_type);
+ i64 otsz = type_size_of(original_type);
+ if (ftsz != otsz) {
+ // TODO(bill): Handle this case which will be caused by #packed most likely
+ GB_PANIC("Incorrectly handled case for handle_struct_system_v_amd64_abi_type, %lld vs %lld", ftsz, otsz);
+ }
+
return final_type;
}
}
diff --git a/src/checker.cpp b/src/checker.cpp
index f30273439..8ce9d8ec2 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -3367,8 +3367,9 @@ bool collect_file_decls(CheckerContext *ctx, Array<Ast *> const &decls) {
if (es->expr->kind == Ast_CallExpr) {
ast_node(ce, CallExpr, es->expr);
if (ce->proc->kind == Ast_BasicDirective) {
- Operand o = {};
- check_expr(ctx, &o, es->expr);
+ if (ctx->collect_delayed_decls) {
+ array_add(&ctx->scope->delayed_directives, es->expr);
+ }
}
}
case_end;
@@ -3525,12 +3526,18 @@ void check_import_entities(Checker *c) {
for_array(i, pkg->files) {
AstFile *f = pkg->files[i];
CheckerContext ctx = c->init_ctx;
-
add_curr_ast_file(&ctx, f);
+
for_array(j, f->scope->delayed_imports) {
Ast *decl = f->scope->delayed_imports[j];
check_add_import_decl(&ctx, decl);
}
+ }
+ for_array(i, pkg->files) {
+ AstFile *f = pkg->files[i];
+ CheckerContext ctx = c->init_ctx;
+ add_curr_ast_file(&ctx, f);
+
for_array(j, f->scope->delayed_directives) {
Ast *expr = f->scope->delayed_directives[j];
Operand o = {};
diff --git a/src/checker.hpp b/src/checker.hpp
index 58cb01a82..f86acce5c 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -222,6 +222,7 @@ struct ForeignContext {
typedef Array<Entity *> CheckerTypePath;
typedef Array<Type *> CheckerPolyPath;
+
// CheckerInfo stores all the symbol information for a type-checked program
struct CheckerInfo {
Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo
diff --git a/src/main.cpp b/src/main.cpp
index b294e7f96..78859e04e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -445,7 +445,7 @@ bool parse_build_flags(Array<String> args) {
path = substring(path, 0, string_extension_position(path));
}
#endif
- build_context.out_filepath = path;
+ build_context.out_filepath = path_to_full_path(heap_allocator(), path);
} else {
gb_printf_err("Invalid -out path, got %.*s\n", LIT(path));
bad_flags = true;
@@ -624,7 +624,7 @@ bool parse_build_flags(Array<String> args) {
break;
}
- if (str == "dll") {
+ if (str == "dll" || str == "shared") {
build_context.is_dll = true;
} else if (str == "exe") {
build_context.is_dll = false;
@@ -1112,7 +1112,7 @@ int main(int arg_count, char **arg_ptr) {
if (0) {
#ifdef GB_SYSTEM_UNIX
} else if (selected_target_metrics->metrics == &target_essence_amd64) {
- system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s",
+ system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s",
LIT(output_base), LIT(output_base), LIT(build_context.link_flags));
#endif
} else {
@@ -1239,10 +1239,7 @@ int main(int arg_count, char **arg_ptr) {
// This allows you to specify '-f' in a #foreign_system_library,
// without having to implement any new syntax specifically for MacOS.
#if defined(GB_SYSTEM_OSX)
- if (lib.len > 2 && lib[0] == '-' && lib[1] == 'f') {
- // framework thingie
- lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
- } else if (string_ends_with(lib, str_lit(".framework"))) {
+ if (string_ends_with(lib, str_lit(".framework"))) {
// framework thingie
String lib_name = lib;
lib_name = remove_extension_from_path(lib_name);
@@ -1251,8 +1248,7 @@ int main(int arg_count, char **arg_ptr) {
// static libs, absolute full path relative to the file in which the lib was imported from
lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib));
} else if (string_ends_with(lib, str_lit(".dylib"))) {
- // dynamic lib, relative path to executable
- // lib_str = gb_string_append_fmt(lib_str, " -l:%s/%.*s ", cwd, LIT(lib));
+ // dynamic lib
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
} else {
// dynamic or static system lib, just link regularly searching system library paths
diff --git a/src/parser.cpp b/src/parser.cpp
index 025a181ba..f69efc0ce 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -3970,34 +3970,6 @@ Ast *parse_stmt(AstFile *f) {
return s;
}
- // case Token_static: {
- // CommentGroup *docs = f->lead_comment;
- // Token token = expect_token(f, Token_static);
-
- // Ast *decl = nullptr;
- // Array<Ast *> list = parse_lhs_expr_list(f);
- // if (list.count == 0) {
- // syntax_error(token, "Illegal use of 'static' statement");
- // expect_semicolon(f, nullptr);
- // return ast_bad_stmt(f, token, f->curr_token);
- // }
-
- // expect_token_after(f, Token_Colon, "identifier list");
- // decl = parse_value_decl(f, list, docs);
-
- // if (decl != nullptr && decl->kind == Ast_ValueDecl) {
- // if (decl->ValueDecl.is_mutable) {
- // decl->ValueDecl.is_static = true;
- // } else {
- // error(token, "'static' may only be currently used with variable declaration");
- // }
- // return decl;
- // }
-
- // syntax_error(token, "Illegal use of 'static' statement");
- // return ast_bad_stmt(f, token, f->curr_token);
- // } break;
-
case Token_using: {
CommentGroup *docs = f->lead_comment;
Token token = expect_token(f, Token_using);
@@ -4071,12 +4043,10 @@ Ast *parse_stmt(AstFile *f) {
} else if (tag == "assert") {
Ast *t = ast_basic_directive(f, hash_token, tag);
return ast_expr_stmt(f, parse_call_expr(f, t));
- } /* else if (name.string == "no_deferred") {
- s = parse_stmt(f);
- s->stmt_state_flags |= StmtStateFlag_no_deferred;
- } */
-
- if (tag == "include") {
+ } else if (tag == "panic") {
+ Ast *t = ast_basic_directive(f, hash_token, tag);
+ return ast_expr_stmt(f, parse_call_expr(f, t));
+ } else if (tag == "include") {
syntax_error(token, "#include is not a valid import declaration kind. Did you mean 'import'?");
s = ast_bad_stmt(f, token, f->curr_token);
} else {
diff --git a/src/types.cpp b/src/types.cpp
index d8a579510..8ad352f62 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -113,21 +113,22 @@ struct BasicType {
struct TypeStruct {
Array<Entity *> fields;
Array<String> tags;
- Ast *node;
- Scope * scope;
-
- Array<i64> offsets;
- bool are_offsets_set;
- bool are_offsets_being_processed;
- bool is_packed;
- bool is_raw_union;
- bool is_polymorphic;
- bool is_poly_specialized;
+ Array<i64> offsets;
+ Ast * node;
+ Scope * scope;
+
Type * polymorphic_params; // Type_Tuple
Type * polymorphic_parent;
- i64 custom_align; // NOTE(bill): Only used in structs at the moment
+ i64 custom_align;
Entity * names;
+
+ bool are_offsets_set;
+ bool are_offsets_being_processed;
+ bool is_packed;
+ bool is_raw_union;
+ bool is_polymorphic;
+ bool is_poly_specialized;
};
struct TypeUnion {
@@ -137,12 +138,11 @@ struct TypeUnion {
i64 variant_block_size;
i64 custom_align;
i64 tag_size;
+ Type * polymorphic_params; // Type_Tuple
+ Type * polymorphic_parent;
bool no_nil;
-
- bool is_polymorphic;
- bool is_poly_specialized;
- Type * polymorphic_params; // Type_Tuple
- Type * polymorphic_parent;
+ bool is_polymorphic;
+ bool is_poly_specialized;
};
#define TYPE_KINDS \
@@ -190,7 +190,9 @@ struct TypeUnion {
TYPE_KIND(Tuple, struct { \
Array<Entity *> variables; /* Entity_Variable */ \
Array<i64> offsets; \
+ bool are_offsets_being_processed; \
bool are_offsets_set; \
+ bool is_packed; \
}) \
TYPE_KIND(Proc, struct { \
Ast *node; \
@@ -201,9 +203,8 @@ struct TypeUnion {
i32 result_count; \
Array<Type *> abi_compat_params; \
Type * abi_compat_result_type; \
- bool return_by_pointer; \
- bool variadic; \
i32 variadic_index; \
+ bool variadic; \
bool require_results; \
bool c_vararg; \
bool is_polymorphic; \
@@ -211,6 +212,7 @@ struct TypeUnion {
bool has_proc_default_values; \
bool has_named_results; \
bool diverging; /* no return */ \
+ bool return_by_pointer; \
u64 tags; \
isize specialization_count; \
ProcCallingConvention calling_convention; \
@@ -1782,7 +1784,8 @@ bool are_types_identical(Type *x, Type *y) {
case Type_Tuple:
if (y->kind == Type_Tuple) {
- if (x->Tuple.variables.count == y->Tuple.variables.count) {
+ if (x->Tuple.variables.count == y->Tuple.variables.count &&
+ x->Tuple.is_packed == y->Tuple.is_packed) {
for_array(i, x->Tuple.variables) {
Entity *xe = x->Tuple.variables[i];
Entity *ye = y->Tuple.variables[i];
@@ -2231,19 +2234,22 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
if (type->Array.count <= 4) {
// HACK(bill): Memory leak
switch (type->Array.count) {
- #define _ARRAY_FIELD_CASE(_length, _name) \
- case (_length): \
- if (field_name == _name) { \
+ #define _ARRAY_FIELD_CASE_IF(_length, _name) \
+ if (field_name == (_name)) { \
selection_add_index(&sel, (_length)-1); \
sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \
return sel; \
- } \
+ }
+ #define _ARRAY_FIELD_CASE(_length, _name0, _name1) \
+ case (_length): \
+ _ARRAY_FIELD_CASE_IF(_length, _name0); \
+ _ARRAY_FIELD_CASE_IF(_length, _name1); \
/*fallthrough*/
- _ARRAY_FIELD_CASE(4, "w");
- _ARRAY_FIELD_CASE(3, "z");
- _ARRAY_FIELD_CASE(2, "y");
- _ARRAY_FIELD_CASE(1, "x");
+ _ARRAY_FIELD_CASE(4, "w", "a");
+ _ARRAY_FIELD_CASE(3, "z", "b");
+ _ARRAY_FIELD_CASE(2, "y", "g");
+ _ARRAY_FIELD_CASE(1, "x", "r");
default: break;
#undef _ARRAY_FIELD_CASE
@@ -2590,9 +2596,9 @@ bool type_set_offsets(Type *t) {
}
} else if (is_type_tuple(t)) {
if (!t->Tuple.are_offsets_set) {
- t->Struct.are_offsets_being_processed = true;
- t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, false, false);
- t->Struct.are_offsets_being_processed = false;
+ t->Tuple.are_offsets_being_processed = true;
+ t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false);
+ t->Tuple.are_offsets_being_processed = false;
t->Tuple.are_offsets_set = true;
return true;
}