mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
#panic; Minor change to demo.odin; Fix #assert bug at file scope
This commit is contained in:
@@ -1091,7 +1091,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
|||||||
case: error(p, stmt.pos, "#complete can only be applied to a switch statement");
|
case: error(p, stmt.pos, "#complete can only be applied to a switch statement");
|
||||||
}
|
}
|
||||||
return stmt;
|
return stmt;
|
||||||
case "assert":
|
case "assert", "panic":
|
||||||
bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(tag));
|
bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(tag));
|
||||||
bd.tok = tok;
|
bd.tok = tok;
|
||||||
bd.name = name;
|
bd.name = name;
|
||||||
|
|||||||
+28
-26
@@ -6,6 +6,7 @@ package runtime
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
import "intrinsics"
|
||||||
|
|
||||||
// Naming Conventions:
|
// Naming Conventions:
|
||||||
// In general, Ada_Case for types and snake_case for values
|
// In general, Ada_Case for types and snake_case for values
|
||||||
@@ -187,12 +188,13 @@ Typeid_Kind :: enum u8 {
|
|||||||
#assert(len(Typeid_Kind) < 32);
|
#assert(len(Typeid_Kind) < 32);
|
||||||
|
|
||||||
Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
|
Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
|
||||||
index: 8*size_of(align_of(uintptr)) - 8,
|
index: 8*size_of(uintptr) - 8,
|
||||||
kind: 5, // Typeid_Kind
|
kind: 5, // Typeid_Kind
|
||||||
named: 1,
|
named: 1,
|
||||||
special: 1, // signed, cstring, etc
|
special: 1, // signed, cstring, etc
|
||||||
reserved: 1,
|
reserved: 1,
|
||||||
}
|
}
|
||||||
|
#assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
|
||||||
|
|
||||||
// NOTE(bill): only the ones that are needed (not all types)
|
// NOTE(bill): only the ones that are needed (not all types)
|
||||||
// This will be set by the compiler
|
// This will be set by the compiler
|
||||||
@@ -678,7 +680,7 @@ assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool
|
|||||||
if p == nil {
|
if p == nil {
|
||||||
p = default_assertion_failure_proc;
|
p = default_assertion_failure_proc;
|
||||||
}
|
}
|
||||||
p("Runtime assertion", message, loc);
|
p("runtime assertion", message, loc);
|
||||||
}(message, loc);
|
}(message, loc);
|
||||||
}
|
}
|
||||||
return condition;
|
return condition;
|
||||||
@@ -690,7 +692,7 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
|
|||||||
if p == nil {
|
if p == nil {
|
||||||
p = default_assertion_failure_proc;
|
p = default_assertion_failure_proc;
|
||||||
}
|
}
|
||||||
p("Panic", message, loc);
|
p("panic", message, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
@@ -816,8 +818,7 @@ __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
|
|||||||
value: V,
|
value: V,
|
||||||
};
|
};
|
||||||
|
|
||||||
_, is_string := type_info_base(type_info_of(K)).variant.(Type_Info_String);
|
header.is_key_string = intrinsics.type_is_string(K);
|
||||||
header.is_key_string = is_string;
|
|
||||||
header.entry_size = int(size_of(Entry));
|
header.entry_size = int(size_of(Entry));
|
||||||
header.entry_align = int(align_of(Entry));
|
header.entry_align = int(align_of(Entry));
|
||||||
header.value_offset = uintptr(offset_of(Entry, value));
|
header.value_offset = uintptr(offset_of(Entry, value));
|
||||||
@@ -828,33 +829,34 @@ __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
|
|||||||
__get_map_key :: proc "contextless" (k: $K) -> Map_Key {
|
__get_map_key :: proc "contextless" (k: $K) -> Map_Key {
|
||||||
key := k;
|
key := k;
|
||||||
map_key: Map_Key;
|
map_key: Map_Key;
|
||||||
ti := type_info_base_without_enum(type_info_of(K));
|
|
||||||
switch _ in ti.variant {
|
T :: intrinsics.type_core_type(K);
|
||||||
case Type_Info_Integer:
|
|
||||||
switch 8*size_of(key) {
|
when intrinsics.type_is_integer(T) {
|
||||||
case 8: map_key.hash = u64(( ^u8)(&key)^);
|
sz :: 8*size_of(T);
|
||||||
case 16: map_key.hash = u64(( ^u16)(&key)^);
|
when sz == 8 do map_key.hash = u64(( ^u8)(&key)^);
|
||||||
case 32: map_key.hash = u64(( ^u32)(&key)^);
|
else when sz == 16 do map_key.hash = u64((^u16)(&key)^);
|
||||||
case 64: map_key.hash = u64(( ^u64)(&key)^);
|
else when sz == 32 do map_key.hash = u64((^u32)(&key)^);
|
||||||
case: panic("Unhandled integer size");
|
else when sz == 64 do map_key.hash = u64((^u64)(&key)^);
|
||||||
}
|
else do #assert(false, "Unhandled integer size");
|
||||||
case Type_Info_Rune:
|
} else when intrinsics.type_is_rune(T) {
|
||||||
map_key.hash = u64((^rune)(&key)^);
|
map_key.hash = u64((^rune)(&key)^);
|
||||||
case Type_Info_Pointer:
|
} else when intrinsics.type_is_pointer(T) {
|
||||||
map_key.hash = u64(uintptr((^rawptr)(&key)^));
|
map_key.hash = u64(uintptr((^rawptr)(&key)^));
|
||||||
case Type_Info_Float:
|
} else when intrinsics.type_is_float(T) {
|
||||||
switch 8*size_of(key) {
|
sz :: 8*size_of(T);
|
||||||
case 32: map_key.hash = u64((^u32)(&key)^);
|
when sz == 32 do map_key.hash = u64((^u32)(&key)^);
|
||||||
case 64: map_key.hash = u64((^u64)(&key)^);
|
else when sz == 64 do map_key.hash = u64((^u64)(&key)^);
|
||||||
case: panic("Unhandled float size");
|
else do #assert(false, "Unhandled float size");
|
||||||
}
|
} else when intrinsics.type_is_string(T) {
|
||||||
case Type_Info_String:
|
#assert(T == string);
|
||||||
str := (^string)(&key)^;
|
str := (^string)(&key)^;
|
||||||
map_key.hash = default_hash_string(str);
|
map_key.hash = default_hash_string(str);
|
||||||
map_key.str = str;
|
map_key.str = str;
|
||||||
case:
|
} else {
|
||||||
panic("Unhandled map key type");
|
#assert(false, "Unhandled map key type");
|
||||||
}
|
}
|
||||||
|
|
||||||
return map_key;
|
return map_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -28,9 +28,9 @@ when os.OS == "windows" {
|
|||||||
Answers to common questions about Odin.
|
Answers to common questions about Odin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@(link_name="general_stuff")
|
@(link_name="extra_general_stuff")
|
||||||
general_stuff :: proc() {
|
extra_general_stuff :: proc() {
|
||||||
fmt.println("# general_stuff");
|
fmt.println("# extra_general_stuff");
|
||||||
{ // `do` for inline statements rather than block
|
{ // `do` for inline statements rather than block
|
||||||
foo :: proc() do fmt.println("Foo!");
|
foo :: proc() do fmt.println("Foo!");
|
||||||
if false do foo();
|
if false do foo();
|
||||||
@@ -209,8 +209,8 @@ union_type :: proc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 :: struct {x, y, z: f32};
|
Vector3 :: distinct [3]f32;
|
||||||
Quaternion :: struct {x, y, z, w: f32};
|
Quaternion :: distinct quaternion128;
|
||||||
|
|
||||||
// More realistic examples
|
// More realistic examples
|
||||||
{
|
{
|
||||||
@@ -320,17 +320,17 @@ union_type :: proc() {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Entity :: struct {
|
Entity :: struct {
|
||||||
..
|
...
|
||||||
derived: union{^Frog, ^Monster},
|
derived: union{^Frog, ^Monster},
|
||||||
}
|
}
|
||||||
|
|
||||||
Frog :: struct {
|
Frog :: struct {
|
||||||
using entity: Entity,
|
using entity: Entity,
|
||||||
..
|
...
|
||||||
}
|
}
|
||||||
Monster :: struct {
|
Monster :: struct {
|
||||||
using entity: Entity,
|
using entity: Entity,
|
||||||
..
|
...
|
||||||
|
|
||||||
}
|
}
|
||||||
new_entity :: proc(T: type) -> ^Entity {
|
new_entity :: proc(T: type) -> ^Entity {
|
||||||
@@ -539,7 +539,7 @@ parametric_polymorphism :: proc() {
|
|||||||
fmt.println(r);
|
fmt.println(r);
|
||||||
r = 123;
|
r = 123;
|
||||||
fmt.println(r);
|
fmt.println(r);
|
||||||
r = Error.Foo0;
|
r = Error.Foo0; // r = .Foo0; is allow too, see implicit selector expressions below
|
||||||
fmt.println(r);
|
fmt.println(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1190,7 +1190,7 @@ where_clauses :: proc() {
|
|||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
when true {
|
when true {
|
||||||
general_stuff();
|
extra_general_stuff();
|
||||||
union_type();
|
union_type();
|
||||||
parametric_polymorphism();
|
parametric_polymorphism();
|
||||||
threading_example();
|
threading_example();
|
||||||
|
|||||||
+20
-2
@@ -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) {
|
||||||
// if (selector->kind != Ast_Ident) {
|
|
||||||
error(selector, "Illegal selector kind: '%.*s'", LIT(ast_strings[selector->kind]));
|
error(selector, "Illegal selector kind: '%.*s'", LIT(ast_strings[selector->kind]));
|
||||||
operand->mode = Addressing_Invalid;
|
operand->mode = Addressing_Invalid;
|
||||||
operand->expr = node;
|
operand->expr = node;
|
||||||
@@ -3544,6 +3543,25 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
|
|
||||||
operand->type = t_untyped_bool;
|
operand->type = t_untyped_bool;
|
||||||
operand->mode = Addressing_Constant;
|
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") {
|
} else if (name == "defined") {
|
||||||
if (ce->args.count != 1) {
|
if (ce->args.count != 1) {
|
||||||
error(call, "'#defined' expects 1 argument, got %td", ce->args.count);
|
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) {
|
ce->proc->kind == Ast_BasicDirective) {
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
String name = bd->name;
|
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->mode = Addressing_Builtin;
|
||||||
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
||||||
operand->expr = ce->proc;
|
operand->expr = ce->proc;
|
||||||
|
|||||||
+31
-8
@@ -1847,7 +1847,7 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
|
|||||||
}
|
}
|
||||||
auto distributed = array_make<Type *>(heap_allocator(), 0, distributed_cap);
|
auto distributed = array_make<Type *>(heap_allocator(), 0, distributed_cap);
|
||||||
|
|
||||||
|
i64 sz = type_size_of(bt);
|
||||||
switch (bt->kind) {
|
switch (bt->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
switch (bt->Basic.kind){
|
switch (bt->Basic.kind){
|
||||||
@@ -1925,9 +1925,9 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
|
|||||||
array_add(&distributed, t_int);
|
array_add(&distributed, t_int);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type_Union:
|
||||||
case Type_DynamicArray:
|
case Type_DynamicArray:
|
||||||
case Type_Map:
|
case Type_Map:
|
||||||
case Type_Union:
|
|
||||||
case Type_BitField: // TODO(bill): Ignore?
|
case Type_BitField: // TODO(bill): Ignore?
|
||||||
// NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet
|
// NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet
|
||||||
goto DEFAULT;
|
goto DEFAULT;
|
||||||
@@ -1937,7 +1937,7 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
|
|||||||
case Type_SimdVector: // TODO(bill): Is this correct logic?
|
case Type_SimdVector: // TODO(bill): Is this correct logic?
|
||||||
default:
|
default:
|
||||||
DEFAULT:;
|
DEFAULT:;
|
||||||
if (type_size_of(bt) > 0) {
|
if (sz > 0) {
|
||||||
array_add(&distributed, bt);
|
array_add(&distributed, bt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1959,13 +1959,22 @@ Type *handle_single_distributed_type_parameter(Array<Type *> const &types, bool
|
|||||||
|
|
||||||
if (types.count == 1) {
|
if (types.count == 1) {
|
||||||
if (offset) *offset = 1;
|
if (offset) *offset = 1;
|
||||||
|
|
||||||
|
i64 sz = type_size_of(types[0]);
|
||||||
|
|
||||||
if (is_type_float(types[0])) {
|
if (is_type_float(types[0])) {
|
||||||
return types[0];
|
return types[0];
|
||||||
} else if (type_size_of(types[0]) == 8) {
|
|
||||||
return types[0];
|
|
||||||
} else {
|
|
||||||
return t_u64;
|
|
||||||
}
|
}
|
||||||
|
switch (sz) {
|
||||||
|
case 0:
|
||||||
|
GB_PANIC("Zero sized type found!");
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
return types[0];
|
||||||
|
}
|
||||||
|
return t_u64;
|
||||||
} else if (types.count >= 2) {
|
} else if (types.count >= 2) {
|
||||||
if (types[0] == t_f32 && types[1] == t_f32) {
|
if (types[0] == t_f32 && types[1] == t_f32) {
|
||||||
if (offset) *offset = 2;
|
if (offset) *offset = 2;
|
||||||
@@ -2050,7 +2059,7 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) {
|
|||||||
Type *final_type = nullptr;
|
Type *final_type = nullptr;
|
||||||
|
|
||||||
if (field_types.count == 0) {
|
if (field_types.count == 0) {
|
||||||
return t;
|
final_type = t;
|
||||||
} else if (field_types.count == 1) {
|
} else if (field_types.count == 1) {
|
||||||
final_type = field_types[0];
|
final_type = field_types[0];
|
||||||
} else {
|
} 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);
|
variables[1] = alloc_entity_param(nullptr, empty_token, two_types[1], false, false);
|
||||||
final_type = alloc_type_tuple();
|
final_type = alloc_type_tuple();
|
||||||
final_type->Tuple.variables = variables;
|
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;
|
return final_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -3367,8 +3367,9 @@ bool collect_file_decls(CheckerContext *ctx, Array<Ast *> const &decls) {
|
|||||||
if (es->expr->kind == Ast_CallExpr) {
|
if (es->expr->kind == Ast_CallExpr) {
|
||||||
ast_node(ce, CallExpr, es->expr);
|
ast_node(ce, CallExpr, es->expr);
|
||||||
if (ce->proc->kind == Ast_BasicDirective) {
|
if (ce->proc->kind == Ast_BasicDirective) {
|
||||||
Operand o = {};
|
if (ctx->collect_delayed_decls) {
|
||||||
check_expr(ctx, &o, es->expr);
|
array_add(&ctx->scope->delayed_directives, es->expr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
@@ -3525,12 +3526,18 @@ void check_import_entities(Checker *c) {
|
|||||||
for_array(i, pkg->files) {
|
for_array(i, pkg->files) {
|
||||||
AstFile *f = pkg->files[i];
|
AstFile *f = pkg->files[i];
|
||||||
CheckerContext ctx = c->init_ctx;
|
CheckerContext ctx = c->init_ctx;
|
||||||
|
|
||||||
add_curr_ast_file(&ctx, f);
|
add_curr_ast_file(&ctx, f);
|
||||||
|
|
||||||
for_array(j, f->scope->delayed_imports) {
|
for_array(j, f->scope->delayed_imports) {
|
||||||
Ast *decl = f->scope->delayed_imports[j];
|
Ast *decl = f->scope->delayed_imports[j];
|
||||||
check_add_import_decl(&ctx, decl);
|
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) {
|
for_array(j, f->scope->delayed_directives) {
|
||||||
Ast *expr = f->scope->delayed_directives[j];
|
Ast *expr = f->scope->delayed_directives[j];
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ struct ForeignContext {
|
|||||||
typedef Array<Entity *> CheckerTypePath;
|
typedef Array<Entity *> CheckerTypePath;
|
||||||
typedef Array<Type *> CheckerPolyPath;
|
typedef Array<Type *> CheckerPolyPath;
|
||||||
|
|
||||||
|
|
||||||
// CheckerInfo stores all the symbol information for a type-checked program
|
// CheckerInfo stores all the symbol information for a type-checked program
|
||||||
struct CheckerInfo {
|
struct CheckerInfo {
|
||||||
Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo
|
Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo
|
||||||
|
|||||||
+5
-9
@@ -445,7 +445,7 @@ bool parse_build_flags(Array<String> args) {
|
|||||||
path = substring(path, 0, string_extension_position(path));
|
path = substring(path, 0, string_extension_position(path));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
build_context.out_filepath = path;
|
build_context.out_filepath = path_to_full_path(heap_allocator(), path);
|
||||||
} else {
|
} else {
|
||||||
gb_printf_err("Invalid -out path, got %.*s\n", LIT(path));
|
gb_printf_err("Invalid -out path, got %.*s\n", LIT(path));
|
||||||
bad_flags = true;
|
bad_flags = true;
|
||||||
@@ -624,7 +624,7 @@ bool parse_build_flags(Array<String> args) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str == "dll") {
|
if (str == "dll" || str == "shared") {
|
||||||
build_context.is_dll = true;
|
build_context.is_dll = true;
|
||||||
} else if (str == "exe") {
|
} else if (str == "exe") {
|
||||||
build_context.is_dll = false;
|
build_context.is_dll = false;
|
||||||
@@ -1112,7 +1112,7 @@ int main(int arg_count, char **arg_ptr) {
|
|||||||
if (0) {
|
if (0) {
|
||||||
#ifdef GB_SYSTEM_UNIX
|
#ifdef GB_SYSTEM_UNIX
|
||||||
} else if (selected_target_metrics->metrics == &target_essence_amd64) {
|
} 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));
|
LIT(output_base), LIT(output_base), LIT(build_context.link_flags));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@@ -1239,10 +1239,7 @@ int main(int arg_count, char **arg_ptr) {
|
|||||||
// This allows you to specify '-f' in a #foreign_system_library,
|
// This allows you to specify '-f' in a #foreign_system_library,
|
||||||
// without having to implement any new syntax specifically for MacOS.
|
// without having to implement any new syntax specifically for MacOS.
|
||||||
#if defined(GB_SYSTEM_OSX)
|
#if defined(GB_SYSTEM_OSX)
|
||||||
if (lib.len > 2 && lib[0] == '-' && lib[1] == 'f') {
|
if (string_ends_with(lib, str_lit(".framework"))) {
|
||||||
// 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"))) {
|
|
||||||
// framework thingie
|
// framework thingie
|
||||||
String lib_name = lib;
|
String lib_name = lib;
|
||||||
lib_name = remove_extension_from_path(lib_name);
|
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
|
// 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));
|
lib_str = gb_string_append_fmt(lib_str, " %.*s ", LIT(lib));
|
||||||
} else if (string_ends_with(lib, str_lit(".dylib"))) {
|
} else if (string_ends_with(lib, str_lit(".dylib"))) {
|
||||||
// dynamic lib, relative path to executable
|
// dynamic lib
|
||||||
// lib_str = gb_string_append_fmt(lib_str, " -l:%s/%.*s ", cwd, LIT(lib));
|
|
||||||
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
|
lib_str = gb_string_append_fmt(lib_str, " -l%.*s ", LIT(lib));
|
||||||
} else {
|
} else {
|
||||||
// dynamic or static system lib, just link regularly searching system library paths
|
// dynamic or static system lib, just link regularly searching system library paths
|
||||||
|
|||||||
+4
-34
@@ -3970,34 +3970,6 @@ Ast *parse_stmt(AstFile *f) {
|
|||||||
return s;
|
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: {
|
case Token_using: {
|
||||||
CommentGroup *docs = f->lead_comment;
|
CommentGroup *docs = f->lead_comment;
|
||||||
Token token = expect_token(f, Token_using);
|
Token token = expect_token(f, Token_using);
|
||||||
@@ -4071,12 +4043,10 @@ Ast *parse_stmt(AstFile *f) {
|
|||||||
} else if (tag == "assert") {
|
} else if (tag == "assert") {
|
||||||
Ast *t = ast_basic_directive(f, hash_token, tag);
|
Ast *t = ast_basic_directive(f, hash_token, tag);
|
||||||
return ast_expr_stmt(f, parse_call_expr(f, t));
|
return ast_expr_stmt(f, parse_call_expr(f, t));
|
||||||
} /* else if (name.string == "no_deferred") {
|
} else if (tag == "panic") {
|
||||||
s = parse_stmt(f);
|
Ast *t = ast_basic_directive(f, hash_token, tag);
|
||||||
s->stmt_state_flags |= StmtStateFlag_no_deferred;
|
return ast_expr_stmt(f, parse_call_expr(f, t));
|
||||||
} */
|
} else if (tag == "include") {
|
||||||
|
|
||||||
if (tag == "include") {
|
|
||||||
syntax_error(token, "#include is not a valid import declaration kind. Did you mean 'import'?");
|
syntax_error(token, "#include is not a valid import declaration kind. Did you mean 'import'?");
|
||||||
s = ast_bad_stmt(f, token, f->curr_token);
|
s = ast_bad_stmt(f, token, f->curr_token);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+35
-29
@@ -113,21 +113,22 @@ struct BasicType {
|
|||||||
struct TypeStruct {
|
struct TypeStruct {
|
||||||
Array<Entity *> fields;
|
Array<Entity *> fields;
|
||||||
Array<String> tags;
|
Array<String> tags;
|
||||||
Ast *node;
|
Array<i64> offsets;
|
||||||
Scope * scope;
|
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;
|
|
||||||
Type * polymorphic_params; // Type_Tuple
|
Type * polymorphic_params; // Type_Tuple
|
||||||
Type * polymorphic_parent;
|
Type * polymorphic_parent;
|
||||||
|
|
||||||
i64 custom_align; // NOTE(bill): Only used in structs at the moment
|
i64 custom_align;
|
||||||
Entity * names;
|
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 {
|
struct TypeUnion {
|
||||||
@@ -137,12 +138,11 @@ struct TypeUnion {
|
|||||||
i64 variant_block_size;
|
i64 variant_block_size;
|
||||||
i64 custom_align;
|
i64 custom_align;
|
||||||
i64 tag_size;
|
i64 tag_size;
|
||||||
|
Type * polymorphic_params; // Type_Tuple
|
||||||
|
Type * polymorphic_parent;
|
||||||
bool no_nil;
|
bool no_nil;
|
||||||
|
bool is_polymorphic;
|
||||||
bool is_polymorphic;
|
bool is_poly_specialized;
|
||||||
bool is_poly_specialized;
|
|
||||||
Type * polymorphic_params; // Type_Tuple
|
|
||||||
Type * polymorphic_parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TYPE_KINDS \
|
#define TYPE_KINDS \
|
||||||
@@ -190,7 +190,9 @@ struct TypeUnion {
|
|||||||
TYPE_KIND(Tuple, struct { \
|
TYPE_KIND(Tuple, struct { \
|
||||||
Array<Entity *> variables; /* Entity_Variable */ \
|
Array<Entity *> variables; /* Entity_Variable */ \
|
||||||
Array<i64> offsets; \
|
Array<i64> offsets; \
|
||||||
|
bool are_offsets_being_processed; \
|
||||||
bool are_offsets_set; \
|
bool are_offsets_set; \
|
||||||
|
bool is_packed; \
|
||||||
}) \
|
}) \
|
||||||
TYPE_KIND(Proc, struct { \
|
TYPE_KIND(Proc, struct { \
|
||||||
Ast *node; \
|
Ast *node; \
|
||||||
@@ -201,9 +203,8 @@ struct TypeUnion {
|
|||||||
i32 result_count; \
|
i32 result_count; \
|
||||||
Array<Type *> abi_compat_params; \
|
Array<Type *> abi_compat_params; \
|
||||||
Type * abi_compat_result_type; \
|
Type * abi_compat_result_type; \
|
||||||
bool return_by_pointer; \
|
|
||||||
bool variadic; \
|
|
||||||
i32 variadic_index; \
|
i32 variadic_index; \
|
||||||
|
bool variadic; \
|
||||||
bool require_results; \
|
bool require_results; \
|
||||||
bool c_vararg; \
|
bool c_vararg; \
|
||||||
bool is_polymorphic; \
|
bool is_polymorphic; \
|
||||||
@@ -211,6 +212,7 @@ struct TypeUnion {
|
|||||||
bool has_proc_default_values; \
|
bool has_proc_default_values; \
|
||||||
bool has_named_results; \
|
bool has_named_results; \
|
||||||
bool diverging; /* no return */ \
|
bool diverging; /* no return */ \
|
||||||
|
bool return_by_pointer; \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
isize specialization_count; \
|
isize specialization_count; \
|
||||||
ProcCallingConvention calling_convention; \
|
ProcCallingConvention calling_convention; \
|
||||||
@@ -1782,7 +1784,8 @@ bool are_types_identical(Type *x, Type *y) {
|
|||||||
|
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
if (y->kind == 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) {
|
for_array(i, x->Tuple.variables) {
|
||||||
Entity *xe = x->Tuple.variables[i];
|
Entity *xe = x->Tuple.variables[i];
|
||||||
Entity *ye = y->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) {
|
if (type->Array.count <= 4) {
|
||||||
// HACK(bill): Memory leak
|
// HACK(bill): Memory leak
|
||||||
switch (type->Array.count) {
|
switch (type->Array.count) {
|
||||||
#define _ARRAY_FIELD_CASE(_length, _name) \
|
#define _ARRAY_FIELD_CASE_IF(_length, _name) \
|
||||||
case (_length): \
|
if (field_name == (_name)) { \
|
||||||
if (field_name == _name) { \
|
|
||||||
selection_add_index(&sel, (_length)-1); \
|
selection_add_index(&sel, (_length)-1); \
|
||||||
sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \
|
sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), type->Array.elem, (_length)-1); \
|
||||||
return sel; \
|
return sel; \
|
||||||
} \
|
}
|
||||||
|
#define _ARRAY_FIELD_CASE(_length, _name0, _name1) \
|
||||||
|
case (_length): \
|
||||||
|
_ARRAY_FIELD_CASE_IF(_length, _name0); \
|
||||||
|
_ARRAY_FIELD_CASE_IF(_length, _name1); \
|
||||||
/*fallthrough*/
|
/*fallthrough*/
|
||||||
|
|
||||||
_ARRAY_FIELD_CASE(4, "w");
|
_ARRAY_FIELD_CASE(4, "w", "a");
|
||||||
_ARRAY_FIELD_CASE(3, "z");
|
_ARRAY_FIELD_CASE(3, "z", "b");
|
||||||
_ARRAY_FIELD_CASE(2, "y");
|
_ARRAY_FIELD_CASE(2, "y", "g");
|
||||||
_ARRAY_FIELD_CASE(1, "x");
|
_ARRAY_FIELD_CASE(1, "x", "r");
|
||||||
default: break;
|
default: break;
|
||||||
|
|
||||||
#undef _ARRAY_FIELD_CASE
|
#undef _ARRAY_FIELD_CASE
|
||||||
@@ -2590,9 +2596,9 @@ bool type_set_offsets(Type *t) {
|
|||||||
}
|
}
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
if (!t->Tuple.are_offsets_set) {
|
if (!t->Tuple.are_offsets_set) {
|
||||||
t->Struct.are_offsets_being_processed = true;
|
t->Tuple.are_offsets_being_processed = true;
|
||||||
t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, false, false);
|
t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false);
|
||||||
t->Struct.are_offsets_being_processed = false;
|
t->Tuple.are_offsets_being_processed = false;
|
||||||
t->Tuple.are_offsets_set = true;
|
t->Tuple.are_offsets_set = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user