mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07: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");
|
||||
}
|
||||
return stmt;
|
||||
case "assert":
|
||||
case "assert", "panic":
|
||||
bd := ast.new(ast.Basic_Directive, tok.pos, end_pos(tag));
|
||||
bd.tok = tok;
|
||||
bd.name = name;
|
||||
|
||||
+28
-26
@@ -6,6 +6,7 @@ package runtime
|
||||
import "core:os"
|
||||
import "core:mem"
|
||||
import "core:log"
|
||||
import "intrinsics"
|
||||
|
||||
// Naming Conventions:
|
||||
// In general, Ada_Case for types and snake_case for values
|
||||
@@ -187,12 +188,13 @@ Typeid_Kind :: enum u8 {
|
||||
#assert(len(Typeid_Kind) < 32);
|
||||
|
||||
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
|
||||
named: 1,
|
||||
special: 1, // signed, cstring, etc
|
||||
reserved: 1,
|
||||
}
|
||||
#assert(size_of(Typeid_Bit_Field) == size_of(uintptr));
|
||||
|
||||
// NOTE(bill): only the ones that are needed (not all types)
|
||||
// This will be set by the compiler
|
||||
@@ -678,7 +680,7 @@ assert :: proc(condition: bool, message := "", loc := #caller_location) -> bool
|
||||
if p == nil {
|
||||
p = default_assertion_failure_proc;
|
||||
}
|
||||
p("Runtime assertion", message, loc);
|
||||
p("runtime assertion", message, loc);
|
||||
}(message, loc);
|
||||
}
|
||||
return condition;
|
||||
@@ -690,7 +692,7 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
|
||||
if p == nil {
|
||||
p = default_assertion_failure_proc;
|
||||
}
|
||||
p("Panic", message, loc);
|
||||
p("panic", message, loc);
|
||||
}
|
||||
|
||||
@builtin
|
||||
@@ -816,8 +818,7 @@ __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
|
||||
value: V,
|
||||
};
|
||||
|
||||
_, is_string := type_info_base(type_info_of(K)).variant.(Type_Info_String);
|
||||
header.is_key_string = is_string;
|
||||
header.is_key_string = intrinsics.type_is_string(K);
|
||||
header.entry_size = int(size_of(Entry));
|
||||
header.entry_align = int(align_of(Entry));
|
||||
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 {
|
||||
key := k;
|
||||
map_key: Map_Key;
|
||||
ti := type_info_base_without_enum(type_info_of(K));
|
||||
switch _ in ti.variant {
|
||||
case Type_Info_Integer:
|
||||
switch 8*size_of(key) {
|
||||
case 8: map_key.hash = u64(( ^u8)(&key)^);
|
||||
case 16: map_key.hash = u64(( ^u16)(&key)^);
|
||||
case 32: map_key.hash = u64(( ^u32)(&key)^);
|
||||
case 64: map_key.hash = u64(( ^u64)(&key)^);
|
||||
case: panic("Unhandled integer size");
|
||||
}
|
||||
case Type_Info_Rune:
|
||||
|
||||
T :: intrinsics.type_core_type(K);
|
||||
|
||||
when intrinsics.type_is_integer(T) {
|
||||
sz :: 8*size_of(T);
|
||||
when sz == 8 do map_key.hash = u64(( ^u8)(&key)^);
|
||||
else when sz == 16 do map_key.hash = u64((^u16)(&key)^);
|
||||
else when sz == 32 do map_key.hash = u64((^u32)(&key)^);
|
||||
else when sz == 64 do map_key.hash = u64((^u64)(&key)^);
|
||||
else do #assert(false, "Unhandled integer size");
|
||||
} else when intrinsics.type_is_rune(T) {
|
||||
map_key.hash = u64((^rune)(&key)^);
|
||||
case Type_Info_Pointer:
|
||||
} else when intrinsics.type_is_pointer(T) {
|
||||
map_key.hash = u64(uintptr((^rawptr)(&key)^));
|
||||
case Type_Info_Float:
|
||||
switch 8*size_of(key) {
|
||||
case 32: map_key.hash = u64((^u32)(&key)^);
|
||||
case 64: map_key.hash = u64((^u64)(&key)^);
|
||||
case: panic("Unhandled float size");
|
||||
}
|
||||
case Type_Info_String:
|
||||
} else when intrinsics.type_is_float(T) {
|
||||
sz :: 8*size_of(T);
|
||||
when sz == 32 do map_key.hash = u64((^u32)(&key)^);
|
||||
else when sz == 64 do map_key.hash = u64((^u64)(&key)^);
|
||||
else do #assert(false, "Unhandled float size");
|
||||
} else when intrinsics.type_is_string(T) {
|
||||
#assert(T == string);
|
||||
str := (^string)(&key)^;
|
||||
map_key.hash = default_hash_string(str);
|
||||
map_key.str = str;
|
||||
case:
|
||||
panic("Unhandled map key type");
|
||||
} else {
|
||||
#assert(false, "Unhandled map key type");
|
||||
}
|
||||
|
||||
return map_key;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -28,9 +28,9 @@ when os.OS == "windows" {
|
||||
Answers to common questions about Odin.
|
||||
*/
|
||||
|
||||
@(link_name="general_stuff")
|
||||
general_stuff :: proc() {
|
||||
fmt.println("# general_stuff");
|
||||
@(link_name="extra_general_stuff")
|
||||
extra_general_stuff :: proc() {
|
||||
fmt.println("# extra_general_stuff");
|
||||
{ // `do` for inline statements rather than block
|
||||
foo :: proc() do fmt.println("Foo!");
|
||||
if false do foo();
|
||||
@@ -209,8 +209,8 @@ union_type :: proc() {
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 :: struct {x, y, z: f32};
|
||||
Quaternion :: struct {x, y, z, w: f32};
|
||||
Vector3 :: distinct [3]f32;
|
||||
Quaternion :: distinct quaternion128;
|
||||
|
||||
// More realistic examples
|
||||
{
|
||||
@@ -320,17 +320,17 @@ union_type :: proc() {
|
||||
|
||||
/*
|
||||
Entity :: struct {
|
||||
..
|
||||
...
|
||||
derived: union{^Frog, ^Monster},
|
||||
}
|
||||
|
||||
Frog :: struct {
|
||||
using entity: Entity,
|
||||
..
|
||||
...
|
||||
}
|
||||
Monster :: struct {
|
||||
using entity: Entity,
|
||||
..
|
||||
...
|
||||
|
||||
}
|
||||
new_entity :: proc(T: type) -> ^Entity {
|
||||
@@ -539,7 +539,7 @@ parametric_polymorphism :: proc() {
|
||||
fmt.println(r);
|
||||
r = 123;
|
||||
fmt.println(r);
|
||||
r = Error.Foo0;
|
||||
r = Error.Foo0; // r = .Foo0; is allow too, see implicit selector expressions below
|
||||
fmt.println(r);
|
||||
}
|
||||
|
||||
@@ -1190,7 +1190,7 @@ where_clauses :: proc() {
|
||||
|
||||
main :: proc() {
|
||||
when true {
|
||||
general_stuff();
|
||||
extra_general_stuff();
|
||||
union_type();
|
||||
parametric_polymorphism();
|
||||
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) {
|
||||
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;
|
||||
|
||||
+31
-8
@@ -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) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-3
@@ -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 = {};
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-9
@@ -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
|
||||
|
||||
+4
-34
@@ -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 {
|
||||
|
||||
+35
-29
@@ -113,21 +113,22 @@ struct BasicType {
|
||||
struct TypeStruct {
|
||||
Array<Entity *> fields;
|
||||
Array<String> tags;
|
||||
Ast *node;
|
||||
Scope * scope;
|
||||
Array<i64> offsets;
|
||||
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_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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user