mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 20:58:15 +00:00
Remove special shared scope for runtime stuff
This commit is contained in:
+64
-64
@@ -1,11 +1,11 @@
|
|||||||
package fmt
|
package fmt
|
||||||
|
|
||||||
|
import "core:runtime"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
import "core:types"
|
import "core:types"
|
||||||
import "core:strconv"
|
import "core:strconv"
|
||||||
import "core:raw"
|
|
||||||
|
|
||||||
|
|
||||||
_BUFFER_SIZE :: 1<<12;
|
_BUFFER_SIZE :: 1<<12;
|
||||||
@@ -33,8 +33,8 @@ Fmt_Info :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
|
string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
|
||||||
s := transmute(raw.Slice)backing;
|
s := transmute(mem.Raw_Slice)backing;
|
||||||
d := raw.Dynamic_Array{
|
d := mem.Raw_Dynamic_Array{
|
||||||
data = s.data,
|
data = s.data,
|
||||||
len = 0,
|
len = 0,
|
||||||
cap = s.len,
|
cap = s.len,
|
||||||
@@ -145,7 +145,7 @@ bprintf :: proc(buf: []byte, fmt: string, args: ...any) -> string {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
|
fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) {
|
||||||
data: [_BUFFER_SIZE]byte;
|
data: [_BUFFER_SIZE]byte;
|
||||||
buf := string_buffer_from_slice(data[..]);
|
buf := string_buffer_from_slice(data[..]);
|
||||||
write_type(&buf, info);
|
write_type(&buf, info);
|
||||||
@@ -156,18 +156,18 @@ write_typeid :: proc(buf: ^String_Buffer, id: typeid) {
|
|||||||
write_type(buf, type_info_of(id));
|
write_type(buf, type_info_of(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) {
|
||||||
if ti == nil {
|
if ti == nil {
|
||||||
write_string(buf, "nil");
|
write_string(buf, "nil");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch info in ti.variant {
|
switch info in ti.variant {
|
||||||
case Type_Info_Named:
|
case runtime.Type_Info_Named:
|
||||||
write_string(buf, info.name);
|
write_string(buf, info.name);
|
||||||
case Type_Info_Integer:
|
case runtime.Type_Info_Integer:
|
||||||
a := any{typeid = typeid_of(ti)};
|
a := any{typeid = typeid_of(ti)};
|
||||||
switch _ in a {
|
switch in a {
|
||||||
case int: write_string(buf, "int");
|
case int: write_string(buf, "int");
|
||||||
case uint: write_string(buf, "uint");
|
case uint: write_string(buf, "uint");
|
||||||
case uintptr: write_string(buf, "uintptr");
|
case uintptr: write_string(buf, "uintptr");
|
||||||
@@ -175,47 +175,47 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
write_byte(buf, info.signed ? 'i' : 'u');
|
write_byte(buf, info.signed ? 'i' : 'u');
|
||||||
write_i64(buf, i64(8*ti.size), 10);
|
write_i64(buf, i64(8*ti.size), 10);
|
||||||
}
|
}
|
||||||
case Type_Info_Rune:
|
case runtime.Type_Info_Rune:
|
||||||
write_string(buf, "rune");
|
write_string(buf, "rune");
|
||||||
case Type_Info_Float:
|
case runtime.Type_Info_Float:
|
||||||
write_byte(buf, 'f');
|
write_byte(buf, 'f');
|
||||||
write_i64(buf, i64(8*ti.size), 10);
|
write_i64(buf, i64(8*ti.size), 10);
|
||||||
case Type_Info_Complex:
|
case runtime.Type_Info_Complex:
|
||||||
write_string(buf, "complex");
|
write_string(buf, "complex");
|
||||||
write_i64(buf, i64(8*ti.size), 10);
|
write_i64(buf, i64(8*ti.size), 10);
|
||||||
case Type_Info_String:
|
case runtime.Type_Info_String:
|
||||||
if info.is_cstring {
|
if info.is_cstring {
|
||||||
write_string(buf, "cstring");
|
write_string(buf, "cstring");
|
||||||
} else {
|
} else {
|
||||||
write_string(buf, "string");
|
write_string(buf, "string");
|
||||||
}
|
}
|
||||||
case Type_Info_Boolean:
|
case runtime.Type_Info_Boolean:
|
||||||
a := any{typeid = typeid_of(ti)};
|
a := any{typeid = typeid_of(ti)};
|
||||||
switch _ in a {
|
switch in a {
|
||||||
case bool: write_string(buf, "bool");
|
case bool: write_string(buf, "bool");
|
||||||
case:
|
case:
|
||||||
write_byte(buf, 'b');
|
write_byte(buf, 'b');
|
||||||
write_i64(buf, i64(8*ti.size), 10);
|
write_i64(buf, i64(8*ti.size), 10);
|
||||||
}
|
}
|
||||||
case Type_Info_Any:
|
case runtime.Type_Info_Any:
|
||||||
write_string(buf, "any");
|
write_string(buf, "any");
|
||||||
|
|
||||||
case Type_Info_Type_Id:
|
case runtime.Type_Info_Type_Id:
|
||||||
write_string(buf, "typeid");
|
write_string(buf, "typeid");
|
||||||
|
|
||||||
case Type_Info_Pointer:
|
case runtime.Type_Info_Pointer:
|
||||||
if info.elem == nil {
|
if info.elem == nil {
|
||||||
write_string(buf, "rawptr");
|
write_string(buf, "rawptr");
|
||||||
} else {
|
} else {
|
||||||
write_string(buf, "^");
|
write_string(buf, "^");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
}
|
}
|
||||||
case Type_Info_Procedure:
|
case runtime.Type_Info_Procedure:
|
||||||
write_string(buf, "proc");
|
write_string(buf, "proc");
|
||||||
if info.params == nil {
|
if info.params == nil {
|
||||||
write_string(buf, "()");
|
write_string(buf, "()");
|
||||||
} else {
|
} else {
|
||||||
t := info.params.variant.(Type_Info_Tuple);
|
t := info.params.variant.(runtime.Type_Info_Tuple);
|
||||||
write_string(buf, "(");
|
write_string(buf, "(");
|
||||||
for t, i in t.types {
|
for t, i in t.types {
|
||||||
if i > 0 do write_string(buf, ", ");
|
if i > 0 do write_string(buf, ", ");
|
||||||
@@ -227,7 +227,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
write_string(buf, " -> ");
|
write_string(buf, " -> ");
|
||||||
write_type(buf, info.results);
|
write_type(buf, info.results);
|
||||||
}
|
}
|
||||||
case Type_Info_Tuple:
|
case runtime.Type_Info_Tuple:
|
||||||
count := len(info.names);
|
count := len(info.names);
|
||||||
if count != 1 do write_string(buf, "(");
|
if count != 1 do write_string(buf, "(");
|
||||||
for name, i in info.names {
|
for name, i in info.names {
|
||||||
@@ -243,25 +243,25 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
if count != 1 do write_string(buf, ")");
|
if count != 1 do write_string(buf, ")");
|
||||||
|
|
||||||
case Type_Info_Array:
|
case runtime.Type_Info_Array:
|
||||||
write_string(buf, "[");
|
write_string(buf, "[");
|
||||||
write_i64(buf, i64(info.count), 10);
|
write_i64(buf, i64(info.count), 10);
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
case Type_Info_Dynamic_Array:
|
case runtime.Type_Info_Dynamic_Array:
|
||||||
write_string(buf, "[dynamic]");
|
write_string(buf, "[dynamic]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
case Type_Info_Slice:
|
case runtime.Type_Info_Slice:
|
||||||
write_string(buf, "[]");
|
write_string(buf, "[]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
|
|
||||||
case Type_Info_Map:
|
case runtime.Type_Info_Map:
|
||||||
write_string(buf, "map[");
|
write_string(buf, "map[");
|
||||||
write_type(buf, info.key);
|
write_type(buf, info.key);
|
||||||
write_byte(buf, ']');
|
write_byte(buf, ']');
|
||||||
write_type(buf, info.value);
|
write_type(buf, info.value);
|
||||||
|
|
||||||
case Type_Info_Struct:
|
case runtime.Type_Info_Struct:
|
||||||
write_string(buf, "struct ");
|
write_string(buf, "struct ");
|
||||||
if info.is_packed do write_string(buf, "#packed ");
|
if info.is_packed do write_string(buf, "#packed ");
|
||||||
if info.is_raw_union do write_string(buf, "#raw_union ");
|
if info.is_raw_union do write_string(buf, "#raw_union ");
|
||||||
@@ -279,7 +279,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
write_byte(buf, '}');
|
write_byte(buf, '}');
|
||||||
|
|
||||||
case Type_Info_Union:
|
case runtime.Type_Info_Union:
|
||||||
write_string(buf, "union {");
|
write_string(buf, "union {");
|
||||||
for variant, i in info.variants {
|
for variant, i in info.variants {
|
||||||
if i > 0 do write_string(buf, ", ");
|
if i > 0 do write_string(buf, ", ");
|
||||||
@@ -287,7 +287,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
write_string(buf, "}");
|
write_string(buf, "}");
|
||||||
|
|
||||||
case Type_Info_Enum:
|
case runtime.Type_Info_Enum:
|
||||||
write_string(buf, "enum ");
|
write_string(buf, "enum ");
|
||||||
write_type(buf, info.base);
|
write_type(buf, info.base);
|
||||||
if info.is_export do write_string(buf, " #export");
|
if info.is_export do write_string(buf, " #export");
|
||||||
@@ -298,7 +298,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
write_string(buf, "}");
|
write_string(buf, "}");
|
||||||
|
|
||||||
case Type_Info_Bit_Field:
|
case runtime.Type_Info_Bit_Field:
|
||||||
write_string(buf, "bit_field ");
|
write_string(buf, "bit_field ");
|
||||||
if ti.align != 1 {
|
if ti.align != 1 {
|
||||||
write_string(buf, "#align ");
|
write_string(buf, "#align ");
|
||||||
@@ -371,7 +371,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
|
|||||||
ok := true;
|
ok := true;
|
||||||
if arg_index < len(args) {
|
if arg_index < len(args) {
|
||||||
arg := args[arg_index];
|
arg := args[arg_index];
|
||||||
arg.typeid = typeid_base(arg.typeid);
|
arg.typeid = runtime.typeid_base(arg.typeid);
|
||||||
switch i in arg {
|
switch i in arg {
|
||||||
case int: num = i;
|
case int: num = i;
|
||||||
case i8: num = int(i);
|
case i8: num = int(i);
|
||||||
@@ -630,13 +630,13 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum_value_to_string :: proc(v: any) -> (string, bool) {
|
enum_value_to_string :: proc(v: any) -> (string, bool) {
|
||||||
v.typeid = typeid_base(v.typeid);
|
v.typeid = runtime.typeid_base(v.typeid);
|
||||||
type_info := type_info_of(v.typeid);
|
type_info := type_info_of(v.typeid);
|
||||||
|
|
||||||
switch e in type_info.variant {
|
switch e in type_info.variant {
|
||||||
case: return "", false;
|
case: return "", false;
|
||||||
case Type_Info_Enum:
|
case runtime.Type_Info_Enum:
|
||||||
get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) {
|
get_str :: proc(i: $T, e: runtime.Type_Info_Enum) -> (string, bool) {
|
||||||
if types.is_string(e.base) {
|
if types.is_string(e.base) {
|
||||||
for val, idx in e.values {
|
for val, idx in e.values {
|
||||||
if v, ok := val.(T); ok && v == i {
|
if v, ok := val.(T); ok && v == i {
|
||||||
@@ -655,7 +655,7 @@ enum_value_to_string :: proc(v: any) -> (string, bool) {
|
|||||||
return "", false;
|
return "", false;
|
||||||
}
|
}
|
||||||
|
|
||||||
a := any{v.data, typeid_of(type_info_base(e.base))};
|
a := any{v.data, typeid_of(runtime.type_info_base(e.base))};
|
||||||
switch v in a {
|
switch v in a {
|
||||||
case rune: return get_str(v, e);
|
case rune: return get_str(v, e);
|
||||||
case i8: return get_str(v, e);
|
case i8: return get_str(v, e);
|
||||||
@@ -701,11 +701,11 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
type_info := type_info_of(v.typeid);
|
type_info := type_info_of(v.typeid);
|
||||||
switch e in type_info.variant {
|
switch e in type_info.variant {
|
||||||
case: fmt_bad_verb(fi, verb);
|
case: fmt_bad_verb(fi, verb);
|
||||||
case Type_Info_Enum:
|
case runtime.Type_Info_Enum:
|
||||||
switch verb {
|
switch verb {
|
||||||
case: fmt_bad_verb(fi, verb);
|
case: fmt_bad_verb(fi, verb);
|
||||||
case 'd', 'f':
|
case 'd', 'f':
|
||||||
fmt_arg(fi, any{v.data, typeid_of(type_info_base(e.base))}, verb);
|
fmt_arg(fi, any{v.data, typeid_of(runtime.type_info_base(e.base))}, verb);
|
||||||
case 's', 'v':
|
case 's', 'v':
|
||||||
str, ok := enum_value_to_string(v);
|
str, ok := enum_value_to_string(v);
|
||||||
if !ok do str = "!%(BAD ENUM VALUE)";
|
if !ok do str = "!%(BAD ENUM VALUE)";
|
||||||
@@ -723,9 +723,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
|
|
||||||
type_info := type_info_of(v.typeid);
|
type_info := type_info_of(v.typeid);
|
||||||
switch info in type_info.variant {
|
switch info in type_info.variant {
|
||||||
case Type_Info_Named:
|
case runtime.Type_Info_Named:
|
||||||
switch b in info.base.variant {
|
switch b in info.base.variant {
|
||||||
case Type_Info_Struct:
|
case runtime.Type_Info_Struct:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -770,21 +770,21 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_value(fi, any{v.data, typeid_of(info.base)}, verb);
|
fmt_value(fi, any{v.data, typeid_of(info.base)}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Boolean: fmt_arg(fi, v, verb);
|
case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb);
|
||||||
case Type_Info_Integer: fmt_arg(fi, v, verb);
|
case runtime.Type_Info_Integer: fmt_arg(fi, v, verb);
|
||||||
case Type_Info_Rune: fmt_arg(fi, v, verb);
|
case runtime.Type_Info_Rune: fmt_arg(fi, v, verb);
|
||||||
case Type_Info_Float: fmt_arg(fi, v, verb);
|
case runtime.Type_Info_Float: fmt_arg(fi, v, verb);
|
||||||
case Type_Info_Complex: fmt_arg(fi, v, verb);
|
case runtime.Type_Info_Complex: fmt_arg(fi, v, verb);
|
||||||
case Type_Info_String: fmt_arg(fi, v, verb);
|
case runtime.Type_Info_String: fmt_arg(fi, v, verb);
|
||||||
|
|
||||||
case Type_Info_Pointer:
|
case runtime.Type_Info_Pointer:
|
||||||
if v.typeid == typeid_of(^Type_Info) {
|
if v.typeid == typeid_of(^runtime.Type_Info) {
|
||||||
write_type(fi.buf, (^^Type_Info)(v.data)^);
|
write_type(fi.buf, (^^runtime.Type_Info)(v.data)^);
|
||||||
} else {
|
} else {
|
||||||
fmt_pointer(fi, (^rawptr)(v.data)^, verb);
|
fmt_pointer(fi, (^rawptr)(v.data)^, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Array:
|
case runtime.Type_Info_Array:
|
||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
for i in 0..info.count {
|
for i in 0..info.count {
|
||||||
@@ -794,10 +794,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Dynamic_Array:
|
case runtime.Type_Info_Dynamic_Array:
|
||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
array := cast(^raw.Dynamic_Array)v.data;
|
array := cast(^mem.Raw_Dynamic_Array)v.data;
|
||||||
for i in 0..array.len {
|
for i in 0..array.len {
|
||||||
if i > 0 do write_string(fi.buf, ", ");
|
if i > 0 do write_string(fi.buf, ", ");
|
||||||
|
|
||||||
@@ -805,10 +805,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Slice:
|
case runtime.Type_Info_Slice:
|
||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
slice := cast(^raw.Slice)v.data;
|
slice := cast(^mem.Raw_Slice)v.data;
|
||||||
for i in 0..slice.len {
|
for i in 0..slice.len {
|
||||||
if i > 0 do write_string(fi.buf, ", ");
|
if i > 0 do write_string(fi.buf, ", ");
|
||||||
|
|
||||||
@@ -816,7 +816,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
fmt_arg(fi, any{rawptr(data), typeid_of(info.elem)}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Map:
|
case runtime.Type_Info_Map:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -825,20 +825,20 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
write_string(fi.buf, "map[");
|
write_string(fi.buf, "map[");
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
|
|
||||||
m := (^raw.Map)(v.data);
|
m := (^mem.Raw_Map)(v.data);
|
||||||
if m != nil {
|
if m != nil {
|
||||||
assert(info.generated_struct != nil);
|
assert(info.generated_struct != nil);
|
||||||
entries := &m.entries;
|
entries := &m.entries;
|
||||||
gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
|
gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct);
|
||||||
ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
|
ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array);
|
||||||
entry_type := ed.elem.variant.(Type_Info_Struct);
|
entry_type := ed.elem.variant.(runtime.Type_Info_Struct);
|
||||||
entry_size := ed.elem_size;
|
entry_size := ed.elem_size;
|
||||||
|
|
||||||
for i in 0..entries.len {
|
for i in 0..entries.len {
|
||||||
if i > 0 do write_string(fi.buf, ", ");
|
if i > 0 do write_string(fi.buf, ", ");
|
||||||
|
|
||||||
data := uintptr(entries.data) + uintptr(i*entry_size);
|
data := uintptr(entries.data) + uintptr(i*entry_size);
|
||||||
header := cast(^__Map_Entry_Header)data;
|
header := cast(^runtime.Map_Entry_Header)data;
|
||||||
|
|
||||||
if types.is_string(info.key) {
|
if types.is_string(info.key) {
|
||||||
write_string(fi.buf, header.key.str);
|
write_string(fi.buf, header.key.str);
|
||||||
@@ -854,7 +854,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Struct:
|
case runtime.Type_Info_Struct:
|
||||||
if info.is_raw_union {
|
if info.is_raw_union {
|
||||||
write_string(fi.buf, "(raw_union)");
|
write_string(fi.buf, "(raw_union)");
|
||||||
return;
|
return;
|
||||||
@@ -890,7 +890,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
if hash do write_string(fi.buf, ",\n");
|
if hash do write_string(fi.buf, ",\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Union:
|
case runtime.Type_Info_Union:
|
||||||
tag_ptr := uintptr(v.data) + info.tag_offset;
|
tag_ptr := uintptr(v.data) + info.tag_offset;
|
||||||
tag_any := any{rawptr(tag_ptr), typeid_of(info.tag_type)};
|
tag_any := any{rawptr(tag_ptr), typeid_of(info.tag_type)};
|
||||||
|
|
||||||
@@ -914,10 +914,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_arg(fi, any{v.data, id}, verb);
|
fmt_arg(fi, any{v.data, id}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Enum:
|
case runtime.Type_Info_Enum:
|
||||||
fmt_enum(fi, v, verb);
|
fmt_enum(fi, v, verb);
|
||||||
|
|
||||||
case Type_Info_Procedure:
|
case runtime.Type_Info_Procedure:
|
||||||
ptr := (^rawptr)(v.data)^;
|
ptr := (^rawptr)(v.data)^;
|
||||||
if ptr == nil {
|
if ptr == nil {
|
||||||
write_string(fi.buf, "nil");
|
write_string(fi.buf, "nil");
|
||||||
@@ -927,7 +927,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
fmt_pointer(fi, ptr, 'p');
|
fmt_pointer(fi, ptr, 'p');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_Info_Type_Id:
|
case runtime.Type_Info_Type_Id:
|
||||||
id := (^typeid)(v.data)^;
|
id := (^typeid)(v.data)^;
|
||||||
write_typeid(fi.buf, id);
|
write_typeid(fi.buf, id);
|
||||||
}
|
}
|
||||||
@@ -960,14 +960,14 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
|||||||
if verb == 'T' {
|
if verb == 'T' {
|
||||||
ti := type_info_of(arg.typeid);
|
ti := type_info_of(arg.typeid);
|
||||||
switch a in arg {
|
switch a in arg {
|
||||||
case ^Type_Info: ti = a;
|
case ^runtime.Type_Info: ti = a;
|
||||||
}
|
}
|
||||||
write_type(fi.buf, ti);
|
write_type(fi.buf, ti);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
base_arg := arg;
|
base_arg := arg;
|
||||||
base_arg.typeid = typeid_base(base_arg.typeid);
|
base_arg.typeid = runtime.typeid_base(base_arg.typeid);
|
||||||
switch a in base_arg {
|
switch a in base_arg {
|
||||||
case bool: fmt_bool(fi, bool(a), verb);
|
case bool: fmt_bool(fi, bool(a), verb);
|
||||||
case b8: fmt_bool(fi, bool(a), verb);
|
case b8: fmt_bool(fi, bool(a), verb);
|
||||||
|
|||||||
+22
-37
@@ -1,7 +1,24 @@
|
|||||||
package mem
|
package mem
|
||||||
|
|
||||||
import "core:raw"
|
DEFAULT_ALIGNMENT :: 2*align_of(rawptr);
|
||||||
import "core:os"
|
|
||||||
|
Allocator_Mode :: enum byte {
|
||||||
|
Alloc,
|
||||||
|
Free,
|
||||||
|
Free_All,
|
||||||
|
Resize,
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr, old_size: int, flags: u64 = 0, location := #caller_location) -> rawptr;
|
||||||
|
|
||||||
|
|
||||||
|
Allocator :: struct {
|
||||||
|
procedure: Allocator_Proc,
|
||||||
|
data: rawptr,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
alloc :: inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
alloc :: inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
||||||
@@ -30,16 +47,16 @@ resize :: inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEF
|
|||||||
|
|
||||||
|
|
||||||
free_string :: proc(str: string, loc := #caller_location) {
|
free_string :: proc(str: string, loc := #caller_location) {
|
||||||
free_ptr(raw.data(str), loc);
|
free_ptr(raw_data(str), loc);
|
||||||
}
|
}
|
||||||
free_cstring :: proc(str: cstring, loc := #caller_location) {
|
free_cstring :: proc(str: cstring, loc := #caller_location) {
|
||||||
free_ptr((^byte)(str), loc);
|
free_ptr((^byte)(str), loc);
|
||||||
}
|
}
|
||||||
free_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
|
free_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
|
||||||
free_ptr(raw.data(array), loc);
|
free_ptr(raw_data(array), loc);
|
||||||
}
|
}
|
||||||
free_slice :: proc(array: $T/[]$E, loc := #caller_location) {
|
free_slice :: proc(array: $T/[]$E, loc := #caller_location) {
|
||||||
free_ptr(raw.data(array), loc);
|
free_ptr(raw_data(array), loc);
|
||||||
}
|
}
|
||||||
free_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
|
free_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
|
||||||
raw := transmute(raw.Map)m;
|
raw := transmute(raw.Map)m;
|
||||||
@@ -78,38 +95,6 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|
||||||
size, alignment: int,
|
|
||||||
old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr {
|
|
||||||
using Allocator_Mode;
|
|
||||||
|
|
||||||
switch mode {
|
|
||||||
case Alloc:
|
|
||||||
return os.heap_alloc(size);
|
|
||||||
|
|
||||||
case Free:
|
|
||||||
os.heap_free(old_memory);
|
|
||||||
return nil;
|
|
||||||
|
|
||||||
case Free_All:
|
|
||||||
// NOTE(bill): Does nothing
|
|
||||||
|
|
||||||
case Resize:
|
|
||||||
ptr := os.heap_resize(old_memory, size);
|
|
||||||
assert(ptr != nil);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
default_allocator :: proc() -> Allocator {
|
|
||||||
return Allocator{
|
|
||||||
procedure = default_allocator_proc,
|
|
||||||
data = nil,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
size, alignment: int,
|
size, alignment: int,
|
||||||
old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr {
|
old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr {
|
||||||
|
|||||||
+13
-13
@@ -1,6 +1,6 @@
|
|||||||
package mem
|
package mem
|
||||||
|
|
||||||
import "core:raw"
|
import "core:runtime"
|
||||||
|
|
||||||
foreign _ {
|
foreign _ {
|
||||||
@(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
|
@(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
|
||||||
@@ -80,20 +80,20 @@ ptr_sub :: proc "contextless" (a, b: $P/^$T) -> int {
|
|||||||
|
|
||||||
slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []T {
|
slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []T {
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
slice := raw.Slice{data = ptr, len = len};
|
slice := Raw_Slice{data = ptr, len = len};
|
||||||
return transmute([]T)slice;
|
return transmute([]T)slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []byte {
|
slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []byte {
|
||||||
s := transmute(raw.Slice)slice;
|
s := transmute(Raw_Slice)slice;
|
||||||
s.len *= size_of(T);
|
s.len *= size_of(T);
|
||||||
return transmute([]byte)s;
|
return transmute([]byte)s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
buffer_from_slice :: proc(backing: $T/[]$E) -> [dynamic]E {
|
buffer_from_slice :: proc(backing: $T/[]$E) -> [dynamic]E {
|
||||||
s := transmute(raw.Slice)backing;
|
s := transmute(Raw_Slice)backing;
|
||||||
d := raw.Dynamic_Array{
|
d := Raw_Dynamic_Array{
|
||||||
data = s.data,
|
data = s.data,
|
||||||
len = 0,
|
len = 0,
|
||||||
cap = s.len,
|
cap = s.len,
|
||||||
@@ -104,13 +104,13 @@ buffer_from_slice :: proc(backing: $T/[]$E) -> [dynamic]E {
|
|||||||
|
|
||||||
ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
|
ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
return transmute([]byte)raw.Slice{ptr, len*size_of(T)};
|
return transmute([]byte)Raw_Slice{ptr, len*size_of(T)};
|
||||||
}
|
}
|
||||||
|
|
||||||
any_to_bytes :: proc "contextless" (val: any) -> []byte {
|
any_to_bytes :: proc "contextless" (val: any) -> []byte {
|
||||||
ti := type_info_of(val.typeid);
|
ti := type_info_of(val.typeid);
|
||||||
size := ti != nil ? ti.size : 0;
|
size := ti != nil ? ti.size : 0;
|
||||||
return transmute([]byte)raw.Slice{val.data, size};
|
return transmute([]byte)Raw_Slice{val.data, size};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -158,8 +158,8 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
|
|||||||
Fixed_Byte_Buffer :: distinct [dynamic]byte;
|
Fixed_Byte_Buffer :: distinct [dynamic]byte;
|
||||||
|
|
||||||
make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer {
|
make_fixed_byte_buffer :: proc(backing: []byte) -> Fixed_Byte_Buffer {
|
||||||
s := transmute(raw.Slice)backing;
|
s := transmute(Raw_Slice)backing;
|
||||||
d: raw.Dynamic_Array;
|
d: Raw_Dynamic_Array;
|
||||||
d.data = s.data;
|
d.data = s.data;
|
||||||
d.len = 0;
|
d.len = 0;
|
||||||
d.cap = s.len;
|
d.cap = s.len;
|
||||||
@@ -199,7 +199,7 @@ init_arena_from_context :: proc(using a: ^Arena, size: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
context_from_allocator :: proc(a: Allocator) -> Context {
|
context_from_allocator :: proc(a: Allocator) -> runtime.Context {
|
||||||
c := context;
|
c := context;
|
||||||
c.allocator = a;
|
c.allocator = a;
|
||||||
return c;
|
return c;
|
||||||
@@ -241,7 +241,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
#no_bounds_check end := &arena.memory[len(arena.memory)];
|
#no_bounds_check end := &arena.memory[len(arena.memory)];
|
||||||
|
|
||||||
ptr := align_forward(end, uintptr(alignment));
|
ptr := align_forward(end, uintptr(alignment));
|
||||||
(^raw.Slice)(&arena.memory).len += total_size;
|
(^Raw_Slice)(&arena.memory).len += total_size;
|
||||||
return zero(ptr, size);
|
return zero(ptr, size);
|
||||||
|
|
||||||
case Free:
|
case Free:
|
||||||
@@ -249,7 +249,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
// Use ArenaTempMemory if you want to free a block
|
// Use ArenaTempMemory if you want to free a block
|
||||||
|
|
||||||
case Free_All:
|
case Free_All:
|
||||||
(^raw.Slice)(&arena.memory).len = 0;
|
(^Raw_Slice)(&arena.memory).len = 0;
|
||||||
|
|
||||||
case Resize:
|
case Resize:
|
||||||
return default_resize_align(old_memory, old_size, size, alignment);
|
return default_resize_align(old_memory, old_size, size, alignment);
|
||||||
@@ -269,7 +269,7 @@ begin_arena_temp_memory :: proc(a: ^Arena) -> ArenaTempMemory {
|
|||||||
end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
|
end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
|
||||||
assert(len(arena.memory) >= original_count);
|
assert(len(arena.memory) >= original_count);
|
||||||
assert(arena.temp_count > 0);
|
assert(arena.temp_count > 0);
|
||||||
(^raw.Dynamic_Array)(&arena.memory).len = original_count;
|
(^Raw_Dynamic_Array)(&arena.memory).len = original_count;
|
||||||
arena.temp_count -= 1;
|
arena.temp_count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package mem
|
||||||
|
|
||||||
|
Raw_Any :: struct {
|
||||||
|
data: rawptr,
|
||||||
|
typeid: typeid,
|
||||||
|
}
|
||||||
|
|
||||||
|
Raw_String :: struct {
|
||||||
|
data: ^byte,
|
||||||
|
len: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
Raw_Cstring :: struct {
|
||||||
|
data: ^byte,
|
||||||
|
}
|
||||||
|
|
||||||
|
Raw_Slice :: struct {
|
||||||
|
data: rawptr,
|
||||||
|
len: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
Raw_Dynamic_Array :: struct {
|
||||||
|
data: rawptr,
|
||||||
|
len: int,
|
||||||
|
cap: int,
|
||||||
|
allocator: Allocator,
|
||||||
|
}
|
||||||
|
|
||||||
|
Raw_Map :: struct {
|
||||||
|
hashes: [dynamic]int,
|
||||||
|
entries: Raw_Dynamic_Array,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
make_any :: inline proc(data: rawptr, id: typeid) -> any {
|
||||||
|
return transmute(any)Raw_Any{data, id};
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_string_data :: inline proc(s: $T/string) -> ^byte {
|
||||||
|
return (^Raw_String)(&s).data;
|
||||||
|
}
|
||||||
|
raw_slice_data :: inline proc(a: $T/[]$E) -> ^E {
|
||||||
|
return cast(^E)(^Raw_Slice)(&a).data;
|
||||||
|
}
|
||||||
|
raw_dynamic_array_data :: inline proc(a: $T/[dynamic]$E) -> ^E {
|
||||||
|
return cast(^E)(^Raw_Dynamic_Array)(&a).data;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_data :: proc[raw_string_data, raw_slice_data, raw_dynamic_array_data];
|
||||||
|
|
||||||
|
|
||||||
+36
-3
@@ -1,6 +1,6 @@
|
|||||||
package os
|
package os
|
||||||
|
|
||||||
import "core:raw"
|
import "core:mem"
|
||||||
|
|
||||||
write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
|
write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
|
||||||
return write(fd, cast([]byte)str);
|
return write(fd, cast([]byte)str);
|
||||||
@@ -56,11 +56,44 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ
|
|||||||
}
|
}
|
||||||
|
|
||||||
write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
|
write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
|
||||||
s := transmute([]byte)raw.Slice{data, len};
|
s := transmute([]byte)mem.Raw_Slice{data, len};
|
||||||
return write(fd, s);
|
return write(fd, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
|
read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
|
||||||
s := transmute([]byte)raw.Slice{data, len};
|
s := transmute([]byte)mem.Raw_Slice{data, len};
|
||||||
return read(fd, s);
|
return read(fd, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
default_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr {
|
||||||
|
using mem.Allocator_Mode;
|
||||||
|
|
||||||
|
switch mode {
|
||||||
|
case Alloc:
|
||||||
|
return heap_alloc(size);
|
||||||
|
|
||||||
|
case Free:
|
||||||
|
heap_free(old_memory);
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
case Free_All:
|
||||||
|
// NOTE(bill): Does nothing
|
||||||
|
|
||||||
|
case Resize:
|
||||||
|
ptr := heap_resize(old_memory, size);
|
||||||
|
assert(ptr != nil);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
default_allocator :: proc() -> mem.Allocator {
|
||||||
|
return mem.Allocator{
|
||||||
|
procedure = default_allocator_proc,
|
||||||
|
data = nil,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
package raw
|
|
||||||
|
|
||||||
Any :: struct {
|
|
||||||
data: rawptr,
|
|
||||||
typeid: typeid,
|
|
||||||
}
|
|
||||||
|
|
||||||
String :: struct {
|
|
||||||
data: ^byte,
|
|
||||||
len: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
Cstring :: struct {
|
|
||||||
data: ^byte,
|
|
||||||
}
|
|
||||||
|
|
||||||
Slice :: struct {
|
|
||||||
data: rawptr,
|
|
||||||
len: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
Dynamic_Array :: struct {
|
|
||||||
data: rawptr,
|
|
||||||
len: int,
|
|
||||||
cap: int,
|
|
||||||
allocator: Allocator,
|
|
||||||
}
|
|
||||||
|
|
||||||
Map :: struct {
|
|
||||||
hashes: [dynamic]int,
|
|
||||||
entries: Dynamic_Array,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
make_any :: inline proc(data: rawptr, id: typeid) -> any {
|
|
||||||
return transmute(any)Any{data, id};
|
|
||||||
}
|
|
||||||
|
|
||||||
string_data :: inline proc(s: $T/string) -> ^byte {
|
|
||||||
return (^String)(&s).data;
|
|
||||||
}
|
|
||||||
slice_data :: inline proc(a: $T/[]$E) -> ^E {
|
|
||||||
return cast(^E)(^Slice)(&a).data;
|
|
||||||
}
|
|
||||||
dynamic_array_data :: inline proc(a: $T/[dynamic]$E) -> ^E {
|
|
||||||
return cast(^E)(^Dynamic_Array)(&a).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
data :: proc[string_data, slice_data, dynamic_array_data];
|
|
||||||
|
|
||||||
|
|
||||||
+71
-82
@@ -4,7 +4,6 @@
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:raw"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|
||||||
// Naming Conventions:
|
// Naming Conventions:
|
||||||
@@ -134,9 +133,9 @@ Type_Info :: struct {
|
|||||||
|
|
||||||
// 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
|
||||||
__type_table: []Type_Info;
|
type_table: []Type_Info;
|
||||||
|
|
||||||
__args__: []cstring;
|
args__: []cstring;
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
||||||
|
|
||||||
@@ -147,27 +146,8 @@ Source_Code_Location :: struct {
|
|||||||
procedure: string,
|
procedure: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator_Mode :: enum byte {
|
|
||||||
Alloc,
|
|
||||||
Free,
|
|
||||||
Free_All,
|
|
||||||
Resize,
|
|
||||||
}
|
|
||||||
|
|
||||||
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|
||||||
size, alignment: int,
|
|
||||||
old_memory: rawptr, old_size: int, flags: u64 = 0, location := #caller_location) -> rawptr;
|
|
||||||
|
|
||||||
|
|
||||||
Allocator :: struct {
|
|
||||||
procedure: Allocator_Proc,
|
|
||||||
data: rawptr,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Context :: struct {
|
Context :: struct {
|
||||||
allocator: Allocator,
|
allocator: mem.Allocator,
|
||||||
thread_id: int,
|
thread_id: int,
|
||||||
|
|
||||||
user_data: any,
|
user_data: any,
|
||||||
@@ -177,34 +157,33 @@ Context :: struct {
|
|||||||
derived: any, // May be used for derived data types
|
derived: any, // May be used for derived data types
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_ALIGNMENT :: 2*align_of(rawptr);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__INITIAL_MAP_CAP :: 16;
|
INITIAL_MAP_CAP :: 16;
|
||||||
|
|
||||||
__Map_Key :: struct {
|
Map_Key :: struct {
|
||||||
hash: u64,
|
hash: u64,
|
||||||
str: string,
|
str: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
__Map_Find_Result :: struct {
|
Map_Find_Result :: struct {
|
||||||
hash_index: int,
|
hash_index: int,
|
||||||
entry_prev: int,
|
entry_prev: int,
|
||||||
entry_index: int,
|
entry_index: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
__Map_Entry_Header :: struct {
|
Map_Entry_Header :: struct {
|
||||||
key: __Map_Key,
|
key: Map_Key,
|
||||||
next: int,
|
next: int,
|
||||||
/*
|
/*
|
||||||
value: Value_Type,
|
value: Value_Type,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
__Map_Header :: struct {
|
Map_Header :: struct {
|
||||||
m: ^raw.Map,
|
m: ^mem.Raw_Map,
|
||||||
is_key_string: bool,
|
is_key_string: bool,
|
||||||
entry_size: int,
|
entry_size: int,
|
||||||
entry_align: int,
|
entry_align: int,
|
||||||
@@ -251,10 +230,10 @@ __typeid_of :: proc "contextless" (ti: ^Type_Info) -> typeid {
|
|||||||
}
|
}
|
||||||
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info {
|
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info {
|
||||||
n := int(transmute(uintptr)id);
|
n := int(transmute(uintptr)id);
|
||||||
if n < 0 || n >= len(__type_table) {
|
if n < 0 || n >= len(type_table) {
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
}
|
||||||
return &__type_table[n];
|
return &type_table[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
||||||
@@ -297,17 +276,13 @@ __init_context_from_ptr :: proc "contextless" (c: ^Context, other: ^Context) {
|
|||||||
__init_context :: proc "contextless" (c: ^Context) {
|
__init_context :: proc "contextless" (c: ^Context) {
|
||||||
if c == nil do return;
|
if c == nil do return;
|
||||||
|
|
||||||
if c.allocator.procedure == nil {
|
c.allocator = os.default_allocator();
|
||||||
c.allocator = mem.default_allocator();
|
c.thread_id = os.current_thread_id();
|
||||||
}
|
|
||||||
if c.thread_id == 0 {
|
|
||||||
c.thread_id = os.current_thread_id();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
copy :: proc "contextless" (dst, src: $T/[]$E) -> int {
|
copy :: proc "contextless" (dst, src: $T/[]$E) -> int {
|
||||||
n := max(0, min(len(dst), len(src)));
|
n := max(0, min(len(dst), len(src)));
|
||||||
if n > 0 do mem.copy(&dst[0], &src[0], n*size_of(E));
|
if n > 0 do mem.copy(&dst[0], &src[0], n*size_of(E));
|
||||||
@@ -316,33 +291,38 @@ copy :: proc "contextless" (dst, src: $T/[]$E) -> int {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E {
|
pop :: proc "contextless" (array: ^$T/[dynamic]$E) -> E {
|
||||||
if array == nil do return E{};
|
if array == nil do return E{};
|
||||||
assert(len(array) > 0);
|
assert(len(array) > 0);
|
||||||
res := array[len(array)-1];
|
res := array[len(array)-1];
|
||||||
(^raw.Dynamic_Array)(array).len -= 1;
|
(^mem.Raw_Dynamic_Array)(array).len -= 1;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
clear :: proc[clear_dynamic_array, clear_map];
|
clear :: proc[clear_dynamic_array, clear_map];
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
reserve :: proc[reserve_dynamic_array, reserve_map];
|
reserve :: proc[reserve_dynamic_array, reserve_map];
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
new :: inline proc(T: type, loc := #caller_location) -> ^T {
|
new :: inline proc(T: type, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(mem.alloc(size_of(T), align_of(T), loc));
|
ptr := (^T)(mem.alloc(size_of(T), align_of(T), loc));
|
||||||
ptr^ = T{};
|
ptr^ = T{};
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
new_clone :: inline proc(data: $T, loc := #caller_location) -> ^T {
|
new_clone :: inline proc(data: $T, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(mem.alloc(size_of(T), align_of(T), loc));
|
ptr := (^T)(mem.alloc(size_of(T), align_of(T), loc));
|
||||||
ptr^ = data;
|
ptr^ = data;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
free :: proc[
|
free :: proc[
|
||||||
mem.free_ptr,
|
mem.free_ptr,
|
||||||
mem.free_string,
|
mem.free_string,
|
||||||
@@ -355,25 +335,29 @@ free :: proc[
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
|
clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
|
||||||
if m == nil do return;
|
if m == nil do return;
|
||||||
raw_map := (^raw.Map)(m);
|
raw_map := (^mem.Raw_Map)(m);
|
||||||
hashes := (^raw.Dynamic_Array)(&raw_map.hashes);
|
hashes := (^mem.Raw_Dynamic_Array)(&raw_map.hashes);
|
||||||
entries := (^raw.Dynamic_Array)(&raw_map.entries);
|
entries := (^mem.Raw_Dynamic_Array)(&raw_map.entries);
|
||||||
hashes.len = 0;
|
hashes.len = 0;
|
||||||
entries.len = 0;
|
entries.len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) {
|
reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) {
|
||||||
if m != nil do __dynamic_map_reserve(__get_map_header(m), capacity);
|
if m != nil do __dynamic_map_reserve(__get_map_header(m), capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
delete :: proc(m: ^$T/map[$K]$V, key: K) {
|
delete :: proc(m: ^$T/map[$K]$V, key: K) {
|
||||||
if m != nil do __dynamic_map_delete(__get_map_header(m), __get_map_key(key));
|
if m != nil do __dynamic_map_delete(__get_map_header(m), __get_map_key(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> int {
|
append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> int {
|
||||||
if array == nil do return 0;
|
if array == nil do return 0;
|
||||||
|
|
||||||
@@ -387,7 +371,7 @@ append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> i
|
|||||||
}
|
}
|
||||||
arg_len = min(cap(array)-len(array), arg_len);
|
arg_len = min(cap(array)-len(array), arg_len);
|
||||||
if arg_len > 0 {
|
if arg_len > 0 {
|
||||||
a := (^raw.Dynamic_Array)(array);
|
a := (^mem.Raw_Dynamic_Array)(array);
|
||||||
data := (^E)(a.data);
|
data := (^E)(a.data);
|
||||||
assert(data != nil);
|
assert(data != nil);
|
||||||
mem.copy(mem.ptr_offset(data, uintptr(a.len)), &args[0], size_of(E) * arg_len);
|
mem.copy(mem.ptr_offset(data, uintptr(a.len)), &args[0], size_of(E) * arg_len);
|
||||||
@@ -396,6 +380,7 @@ append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> i
|
|||||||
return len(array);
|
return len(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ...string, loc := #caller_location) -> int {
|
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ...string, loc := #caller_location) -> int {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
append(array = array, args = ([]E)(arg), loc = loc);
|
append(array = array, args = ([]E)(arg), loc = loc);
|
||||||
@@ -403,13 +388,15 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ...string, loc := #caller
|
|||||||
return len(array);
|
return len(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) {
|
clear_dynamic_array :: inline proc "contextless" (array: ^$T/[dynamic]$E) {
|
||||||
if array != nil do (^raw.Dynamic_Array)(array).len = 0;
|
if array != nil do (^mem.Raw_Dynamic_Array)(array).len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
|
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
|
||||||
if array == nil do return false;
|
if array == nil do return false;
|
||||||
a := (^raw.Dynamic_Array)(array);
|
a := (^mem.Raw_Dynamic_Array)(array);
|
||||||
|
|
||||||
if capacity <= a.cap do return true;
|
if capacity <= a.cap do return true;
|
||||||
|
|
||||||
@@ -423,7 +410,7 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
|
|||||||
allocator := a.allocator;
|
allocator := a.allocator;
|
||||||
|
|
||||||
new_data := allocator.procedure(
|
new_data := allocator.procedure(
|
||||||
allocator.data, Allocator_Mode.Resize, new_size, align_of(E),
|
allocator.data, mem.Allocator_Mode.Resize, new_size, align_of(E),
|
||||||
a.data, old_size, 0, loc,
|
a.data, old_size, 0, loc,
|
||||||
);
|
);
|
||||||
if new_data == nil do return false;
|
if new_data == nil do return false;
|
||||||
@@ -438,6 +425,7 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
assert :: proc "contextless" (condition: bool, message := "", using loc := #caller_location) -> bool {
|
assert :: proc "contextless" (condition: bool, message := "", using loc := #caller_location) -> bool {
|
||||||
if !condition {
|
if !condition {
|
||||||
fd := os.stderr;
|
fd := os.stderr;
|
||||||
@@ -453,6 +441,7 @@ assert :: proc "contextless" (condition: bool, message := "", using loc := #call
|
|||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(builtin)
|
||||||
panic :: proc "contextless" (message := "", using loc := #caller_location) {
|
panic :: proc "contextless" (message := "", using loc := #caller_location) {
|
||||||
fd := os.stderr;
|
fd := os.stderr;
|
||||||
__print_caller_location(fd, loc);
|
__print_caller_location(fd, loc);
|
||||||
@@ -471,7 +460,7 @@ panic :: proc "contextless" (message := "", using loc := #caller_location) {
|
|||||||
|
|
||||||
|
|
||||||
__dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) {
|
__dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int, loc := #caller_location) {
|
||||||
array := (^raw.Dynamic_Array)(array_);
|
array := (^mem.Raw_Dynamic_Array)(array_);
|
||||||
array.allocator = context.allocator;
|
array.allocator = context.allocator;
|
||||||
assert(array.allocator.procedure != nil);
|
assert(array.allocator.procedure != nil);
|
||||||
|
|
||||||
@@ -482,7 +471,7 @@ __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool {
|
__dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool {
|
||||||
array := (^raw.Dynamic_Array)(array_);
|
array := (^mem.Raw_Dynamic_Array)(array_);
|
||||||
|
|
||||||
if cap <= array.cap do return true;
|
if cap <= array.cap do return true;
|
||||||
|
|
||||||
@@ -495,7 +484,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
|
|||||||
new_size := cap * elem_size;
|
new_size := cap * elem_size;
|
||||||
allocator := array.allocator;
|
allocator := array.allocator;
|
||||||
|
|
||||||
new_data := allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, elem_align, array.data, old_size, 0, loc);
|
new_data := allocator.procedure(allocator.data, mem.Allocator_Mode.Resize, new_size, elem_align, array.data, old_size, 0, loc);
|
||||||
if new_data == nil do return false;
|
if new_data == nil do return false;
|
||||||
|
|
||||||
array.data = new_data;
|
array.data = new_data;
|
||||||
@@ -504,7 +493,7 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool {
|
__dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int, loc := #caller_location) -> bool {
|
||||||
array := (^raw.Dynamic_Array)(array_);
|
array := (^mem.Raw_Dynamic_Array)(array_);
|
||||||
|
|
||||||
ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc);
|
ok := __dynamic_array_reserve(array_, elem_size, elem_align, len, loc);
|
||||||
if ok do array.len = len;
|
if ok do array.len = len;
|
||||||
@@ -514,7 +503,7 @@ __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len:
|
|||||||
|
|
||||||
__dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
|
__dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
|
||||||
items: rawptr, item_count: int, loc := #caller_location) -> int {
|
items: rawptr, item_count: int, loc := #caller_location) -> int {
|
||||||
array := (^raw.Dynamic_Array)(array_);
|
array := (^mem.Raw_Dynamic_Array)(array_);
|
||||||
|
|
||||||
if items == nil do return 0;
|
if items == nil do return 0;
|
||||||
if item_count <= 0 do return 0;
|
if item_count <= 0 do return 0;
|
||||||
@@ -537,7 +526,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int {
|
__dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int, loc := #caller_location) -> int {
|
||||||
array := (^raw.Dynamic_Array)(array_);
|
array := (^mem.Raw_Dynamic_Array)(array_);
|
||||||
|
|
||||||
ok := true;
|
ok := true;
|
||||||
if array.cap <= array.len+1 {
|
if array.cap <= array.len+1 {
|
||||||
@@ -559,10 +548,10 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
|
|||||||
|
|
||||||
// Map
|
// Map
|
||||||
|
|
||||||
__get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> __Map_Header {
|
__get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> Map_Header {
|
||||||
header := __Map_Header{m = (^raw.Map)(m)};
|
header := Map_Header{m = (^mem.Raw_Map)(m)};
|
||||||
Entry :: struct {
|
Entry :: struct {
|
||||||
key: __Map_Key,
|
key: Map_Key,
|
||||||
next: int,
|
next: int,
|
||||||
value: V,
|
value: V,
|
||||||
}
|
}
|
||||||
@@ -576,8 +565,8 @@ __get_map_header :: proc "contextless" (m: ^$T/map[$K]$V) -> __Map_Header {
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
__get_map_key :: proc "contextless" (key: $K) -> __Map_Key {
|
__get_map_key :: proc "contextless" (key: $K) -> Map_Key {
|
||||||
map_key: __Map_Key;
|
map_key: Map_Key;
|
||||||
ti := type_info_base_without_enum(type_info_of(K));
|
ti := type_info_base_without_enum(type_info_of(K));
|
||||||
switch _ in ti.variant {
|
switch _ in ti.variant {
|
||||||
case Type_Info_Integer:
|
case Type_Info_Integer:
|
||||||
@@ -621,17 +610,17 @@ __default_hash :: proc(data: []byte) -> u64 {
|
|||||||
}
|
}
|
||||||
__default_hash_string :: proc(s: string) -> u64 do return __default_hash(([]byte)(s));
|
__default_hash_string :: proc(s: string) -> u64 do return __default_hash(([]byte)(s));
|
||||||
|
|
||||||
__dynamic_map_reserve :: proc(using header: __Map_Header, cap: int, loc := #caller_location) {
|
__dynamic_map_reserve :: proc(using header: Map_Header, cap: int, loc := #caller_location) {
|
||||||
__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap, loc);
|
__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap, loc);
|
||||||
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
|
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
|
||||||
}
|
}
|
||||||
__dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc := #caller_location) #no_bounds_check {
|
__dynamic_map_rehash :: proc(using header: Map_Header, new_count: int, loc := #caller_location) #no_bounds_check {
|
||||||
new_header: __Map_Header = header;
|
new_header: Map_Header = header;
|
||||||
nm: raw.Map;
|
nm: mem.Raw_Map;
|
||||||
new_header.m = &nm;
|
new_header.m = &nm;
|
||||||
|
|
||||||
header_hashes := (^raw.Dynamic_Array)(&header.m.hashes);
|
header_hashes := (^mem.Raw_Dynamic_Array)(&header.m.hashes);
|
||||||
nm_hashes := (^raw.Dynamic_Array)(&nm.hashes);
|
nm_hashes := (^mem.Raw_Dynamic_Array)(&nm.hashes);
|
||||||
|
|
||||||
__dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count, loc);
|
__dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count, loc);
|
||||||
__dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
|
__dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len, loc);
|
||||||
@@ -664,7 +653,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc :=
|
|||||||
header.m^ = nm;
|
header.m^ = nm;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
|
__dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr {
|
||||||
index := __dynamic_map_find(h, key).entry_index;
|
index := __dynamic_map_find(h, key).entry_index;
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
data := uintptr(__dynamic_map_get_entry(h, index));
|
data := uintptr(__dynamic_map_get_entry(h, index));
|
||||||
@@ -673,13 +662,13 @@ __dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_set :: proc(h: __Map_Header, key: __Map_Key, value: rawptr, loc := #caller_location) #no_bounds_check {
|
__dynamic_map_set :: proc(h: Map_Header, key: Map_Key, value: rawptr, loc := #caller_location) #no_bounds_check {
|
||||||
|
|
||||||
index: int;
|
index: int;
|
||||||
assert(value != nil);
|
assert(value != nil);
|
||||||
|
|
||||||
if len(h.m.hashes) == 0 {
|
if len(h.m.hashes) == 0 {
|
||||||
__dynamic_map_reserve(h, __INITIAL_MAP_CAP, loc);
|
__dynamic_map_reserve(h, INITIAL_MAP_CAP, loc);
|
||||||
__dynamic_map_grow(h, loc);
|
__dynamic_map_grow(h, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,18 +697,18 @@ __dynamic_map_set :: proc(h: __Map_Header, key: __Map_Key, value: rawptr, loc :=
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__dynamic_map_grow :: proc(using h: __Map_Header, loc := #caller_location) {
|
__dynamic_map_grow :: proc(using h: Map_Header, loc := #caller_location) {
|
||||||
// TODO(bill): Determine an efficient growing rate
|
// TODO(bill): Determine an efficient growing rate
|
||||||
new_count := max(4*m.entries.cap + 7, __INITIAL_MAP_CAP);
|
new_count := max(4*m.entries.cap + 7, INITIAL_MAP_CAP);
|
||||||
__dynamic_map_rehash(h, new_count, loc);
|
__dynamic_map_rehash(h, new_count, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_full :: inline proc(using h: __Map_Header) -> bool {
|
__dynamic_map_full :: inline proc(using h: Map_Header) -> bool {
|
||||||
return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
|
return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
__dynamic_map_hash_equal :: proc(h: __Map_Header, a, b: __Map_Key) -> bool {
|
__dynamic_map_hash_equal :: proc(h: Map_Header, a, b: Map_Key) -> bool {
|
||||||
if a.hash == b.hash {
|
if a.hash == b.hash {
|
||||||
if h.is_key_string do return a.str == b.str;
|
if h.is_key_string do return a.str == b.str;
|
||||||
return true;
|
return true;
|
||||||
@@ -727,8 +716,8 @@ __dynamic_map_hash_equal :: proc(h: __Map_Header, a, b: __Map_Key) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_Result #no_bounds_check {
|
__dynamic_map_find :: proc(using h: Map_Header, key: Map_Key) -> Map_Find_Result #no_bounds_check {
|
||||||
fr := __Map_Find_Result{-1, -1, -1};
|
fr := Map_Find_Result{-1, -1, -1};
|
||||||
if len(m.hashes) > 0 {
|
if len(m.hashes) > 0 {
|
||||||
fr.hash_index = int(key.hash % u64(len(m.hashes)));
|
fr.hash_index = int(key.hash % u64(len(m.hashes)));
|
||||||
fr.entry_index = m.hashes[fr.hash_index];
|
fr.entry_index = m.hashes[fr.hash_index];
|
||||||
@@ -742,7 +731,7 @@ __dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_
|
|||||||
return fr;
|
return fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key, loc := #caller_location) -> int {
|
__dynamic_map_add_entry :: proc(using h: Map_Header, key: Map_Key, loc := #caller_location) -> int {
|
||||||
prev := m.entries.len;
|
prev := m.entries.len;
|
||||||
c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
|
c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
|
||||||
if c != prev {
|
if c != prev {
|
||||||
@@ -753,19 +742,19 @@ __dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key, loc := #c
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_delete :: proc(using h: __Map_Header, key: __Map_Key) {
|
__dynamic_map_delete :: proc(using h: Map_Header, key: Map_Key) {
|
||||||
fr := __dynamic_map_find(h, key);
|
fr := __dynamic_map_find(h, key);
|
||||||
if fr.entry_index >= 0 {
|
if fr.entry_index >= 0 {
|
||||||
__dynamic_map_erase(h, fr);
|
__dynamic_map_erase(h, fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_get_entry :: proc(using h: __Map_Header, index: int) -> ^__Map_Entry_Header {
|
__dynamic_map_get_entry :: proc(using h: Map_Header, index: int) -> ^Map_Entry_Header {
|
||||||
assert(0 <= index && index < m.entries.len);
|
assert(0 <= index && index < m.entries.len);
|
||||||
return (^__Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size));
|
return (^Map_Entry_Header)(uintptr(m.entries.data) + uintptr(index*entry_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) #no_bounds_check {
|
__dynamic_map_erase :: proc(using h: Map_Header, fr: Map_Find_Result) #no_bounds_check {
|
||||||
if fr.entry_prev < 0 {
|
if fr.entry_prev < 0 {
|
||||||
m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
|
m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+10
-10
@@ -1,6 +1,5 @@
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "core:raw"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
@@ -239,7 +238,7 @@ __cstring_to_string :: proc "contextless" (s: cstring) -> string {
|
|||||||
if s == nil do return "";
|
if s == nil do return "";
|
||||||
ptr := (^byte)(s);
|
ptr := (^byte)(s);
|
||||||
n := __cstring_len(s);
|
n := __cstring_len(s);
|
||||||
return transmute(string)raw.String{ptr, n};
|
return transmute(string)mem.Raw_String{ptr, n};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -250,7 +249,7 @@ __complex128_eq :: inline proc "contextless" (a, b: complex128) -> bool { return
|
|||||||
__complex128_ne :: inline proc "contextless" (a, b: complex128) -> bool { return real(a) != real(b) || imag(a) != imag(b); }
|
__complex128_ne :: inline proc "contextless" (a, b: complex128) -> bool { return real(a) != real(b) || imag(a) != imag(b); }
|
||||||
|
|
||||||
|
|
||||||
__bounds_check_error :: proc "contextless" (file: string, line, column: int, index, count: int) {
|
bounds_check_error :: proc "contextless" (file: string, line, column: int, index, count: int) {
|
||||||
if 0 <= index && index < count do return;
|
if 0 <= index && index < count do return;
|
||||||
|
|
||||||
fd := os.stderr;
|
fd := os.stderr;
|
||||||
@@ -263,7 +262,7 @@ __bounds_check_error :: proc "contextless" (file: string, line, column: int, ind
|
|||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
__slice_expr_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) {
|
slice_expr_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) {
|
||||||
if 0 <= lo && lo <= hi && hi <= len do return;
|
if 0 <= lo && lo <= hi && hi <= len do return;
|
||||||
|
|
||||||
|
|
||||||
@@ -279,7 +278,7 @@ __slice_expr_error :: proc "contextless" (file: string, line, column: int, lo, h
|
|||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) {
|
dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) {
|
||||||
if 0 <= low && low <= high && high <= max do return;
|
if 0 <= low && low <= high && high <= max do return;
|
||||||
|
|
||||||
fd := os.stderr;
|
fd := os.stderr;
|
||||||
@@ -294,7 +293,7 @@ __dynamic_array_expr_error :: proc "contextless" (file: string, line, column: in
|
|||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
__type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: int, from, to: typeid) {
|
type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: int, from, to: typeid) {
|
||||||
if ok do return;
|
if ok do return;
|
||||||
|
|
||||||
fd := os.stderr;
|
fd := os.stderr;
|
||||||
@@ -311,11 +310,12 @@ __string_decode_rune :: inline proc "contextless" (s: string) -> (rune, int) {
|
|||||||
return utf8.decode_rune_from_string(s);
|
return utf8.decode_rune_from_string(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
__bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_location, index, count: int) {
|
bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_location, index, count: int) {
|
||||||
__bounds_check_error(file_path, int(line), int(column), index, count);
|
bounds_check_error(file_path, int(line), int(column), index, count);
|
||||||
}
|
}
|
||||||
__slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) {
|
|
||||||
__slice_expr_error(file_path, int(line), int(column), lo, hi, len);
|
slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) {
|
||||||
|
slice_expr_error(file_path, int(line), int(column), lo, hi, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
package runtime
|
|
||||||
|
|
||||||
/*
|
|
||||||
@(link_name="__multi3")
|
|
||||||
__multi3 :: proc "c" (a, b: u128) -> u128 {
|
|
||||||
bits_in_dword_2 :: size_of(i64) * 4;
|
|
||||||
lower_mask :: u128(~u64(0) >> bits_in_dword_2);
|
|
||||||
|
|
||||||
|
|
||||||
when ODIN_ENDIAN == "big" {
|
|
||||||
TWords :: struct #raw_union {
|
|
||||||
all: u128,
|
|
||||||
using _: struct {lo, hi: u64},
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
TWords :: struct #raw_union {
|
|
||||||
all: u128,
|
|
||||||
using _: struct {hi, lo: u64},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
r: TWords;
|
|
||||||
t: u64;
|
|
||||||
|
|
||||||
r.lo = u64(a & lower_mask) * u64(b & lower_mask);
|
|
||||||
t = r.lo >> bits_in_dword_2;
|
|
||||||
r.lo &= u64(lower_mask);
|
|
||||||
t += u64(a >> bits_in_dword_2) * u64(b & lower_mask);
|
|
||||||
r.lo += u64(t & u64(lower_mask)) << bits_in_dword_2;
|
|
||||||
r.hi = t >> bits_in_dword_2;
|
|
||||||
t = r.lo >> bits_in_dword_2;
|
|
||||||
r.lo &= u64(lower_mask);
|
|
||||||
t += u64(b >> bits_in_dword_2) * u64(a & lower_mask);
|
|
||||||
r.lo += u64(t & u64(lower_mask)) << bits_in_dword_2;
|
|
||||||
r.hi += t >> bits_in_dword_2;
|
|
||||||
r.hi += u64(a >> bits_in_dword_2) * u64(b >> bits_in_dword_2);
|
|
||||||
return r.all;
|
|
||||||
}
|
|
||||||
|
|
||||||
@(link_name="__umodti3")
|
|
||||||
__u128_mod :: proc "c" (a, b: u128) -> u128 {
|
|
||||||
r: u128;
|
|
||||||
__u128_quo_mod(a, b, &r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@(link_name="__udivti3")
|
|
||||||
__u128_quo :: proc "c" (a, b: u128) -> u128 {
|
|
||||||
return __u128_quo_mod(a, b, nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
@(link_name="__modti3")
|
|
||||||
__i128_mod :: proc "c" (a, b: i128) -> i128 {
|
|
||||||
r: i128;
|
|
||||||
__i128_quo_mod(a, b, &r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@(link_name="__divti3")
|
|
||||||
__i128_quo :: proc "c" (a, b: i128) -> i128 {
|
|
||||||
return __i128_quo_mod(a, b, nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
@(link_name="__divmodti4")
|
|
||||||
__i128_quo_mod :: proc "c" (a, b: i128, rem: ^i128) -> (quo: i128) {
|
|
||||||
s: i128;
|
|
||||||
s = b >> 127;
|
|
||||||
b = (b~s) - s;
|
|
||||||
s = a >> 127;
|
|
||||||
b = (a~s) - s;
|
|
||||||
|
|
||||||
uquo: u128;
|
|
||||||
urem := __u128_quo_mod(transmute(u128)a, transmute(u128)b, &uquo);
|
|
||||||
iquo := transmute(i128)uquo;
|
|
||||||
irem := transmute(i128)urem;
|
|
||||||
|
|
||||||
iquo = (iquo~s) - s;
|
|
||||||
irem = (irem~s) - s;
|
|
||||||
if rem != nil do rem^ = irem;
|
|
||||||
return iquo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@(link_name="__udivmodti4")
|
|
||||||
__u128_quo_mod :: proc "c" (a, b: u128, rem: ^u128) -> (quo: u128) {
|
|
||||||
alo := u64(a);
|
|
||||||
blo := u64(b);
|
|
||||||
if b == 0 {
|
|
||||||
if rem != nil do rem^ = 0;
|
|
||||||
return u128(alo/blo);
|
|
||||||
}
|
|
||||||
|
|
||||||
r, d, x, q: u128 = a, b, 1, 0;
|
|
||||||
|
|
||||||
for r >= d && (d>>127)&1 == 0 {
|
|
||||||
x <<= 1;
|
|
||||||
d <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for x != 0 {
|
|
||||||
if r >= d {
|
|
||||||
r -= d;
|
|
||||||
q |= x;
|
|
||||||
}
|
|
||||||
x >>= 1;
|
|
||||||
d >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if rem != nil do rem^ = r;
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
package sort
|
package sort
|
||||||
|
|
||||||
|
import "core:mem"
|
||||||
|
|
||||||
bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
|
bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
|
||||||
assert(f != nil);
|
assert(f != nil);
|
||||||
count := len(array);
|
count := len(array);
|
||||||
@@ -211,5 +213,5 @@ compare_f64s :: proc(a, b: f64) -> int {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
compare_strings :: proc(a, b: string) -> int {
|
compare_strings :: proc(a, b: string) -> int {
|
||||||
return __string_cmp(a, b);
|
return mem.compare_byte_ptrs(&a[0], &b[0], min(len(a), len(b)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package strings
|
package strings
|
||||||
|
|
||||||
import "core:raw"
|
import "core:mem"
|
||||||
|
|
||||||
new_string :: proc(s: string) -> string {
|
new_string :: proc(s: string) -> string {
|
||||||
c := make([]byte, len(s)+1);
|
c := make([]byte, len(s)+1);
|
||||||
@@ -22,7 +22,7 @@ to_odin_string :: proc(str: cstring) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string_from_ptr :: proc(ptr: ^byte, len: int) -> string {
|
string_from_ptr :: proc(ptr: ^byte, len: int) -> string {
|
||||||
return transmute(string)raw.String{ptr, len};
|
return transmute(string)mem.Raw_String{ptr, len};
|
||||||
}
|
}
|
||||||
|
|
||||||
contains_rune :: proc(s: string, r: rune) -> int {
|
contains_rune :: proc(s: string, r: rune) -> int {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package thread
|
package thread
|
||||||
|
|
||||||
|
import "core:runtime"
|
||||||
import "core:sys/win32"
|
import "core:sys/win32"
|
||||||
|
|
||||||
Thread_Proc :: #type proc(^Thread) -> int;
|
Thread_Proc :: #type proc(^Thread) -> int;
|
||||||
@@ -15,7 +16,7 @@ Thread :: struct {
|
|||||||
data: rawptr,
|
data: rawptr,
|
||||||
user_index: int,
|
user_index: int,
|
||||||
|
|
||||||
init_context: Context,
|
init_context: runtime.Context,
|
||||||
use_init_context: bool,
|
use_init_context: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+80
-78
@@ -1,6 +1,8 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
import "core:runtime"
|
||||||
|
|
||||||
|
are_types_identical :: proc(a, b: ^runtime.Type_Info) -> bool {
|
||||||
if a == b do return true;
|
if a == b do return true;
|
||||||
|
|
||||||
if (a == nil && b != nil) ||
|
if (a == nil && b != nil) ||
|
||||||
@@ -15,47 +17,47 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch x in a.variant {
|
switch x in a.variant {
|
||||||
case Type_Info_Named:
|
case runtime.Type_Info_Named:
|
||||||
y, ok := b.variant.(Type_Info_Named);
|
y, ok := b.variant.(runtime.Type_Info_Named);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
return x.base == y.base;
|
return x.base == y.base;
|
||||||
|
|
||||||
case Type_Info_Integer:
|
case runtime.Type_Info_Integer:
|
||||||
y, ok := b.variant.(Type_Info_Integer);
|
y, ok := b.variant.(runtime.Type_Info_Integer);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
return x.signed == y.signed;
|
return x.signed == y.signed;
|
||||||
|
|
||||||
case Type_Info_Rune:
|
case runtime.Type_Info_Rune:
|
||||||
_, ok := b.variant.(Type_Info_Rune);
|
_, ok := b.variant.(runtime.Type_Info_Rune);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
case Type_Info_Float:
|
case runtime.Type_Info_Float:
|
||||||
_, ok := b.variant.(Type_Info_Float);
|
_, ok := b.variant.(runtime.Type_Info_Float);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
case Type_Info_Complex:
|
case runtime.Type_Info_Complex:
|
||||||
_, ok := b.variant.(Type_Info_Complex);
|
_, ok := b.variant.(runtime.Type_Info_Complex);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
case Type_Info_String:
|
case runtime.Type_Info_String:
|
||||||
_, ok := b.variant.(Type_Info_String);
|
_, ok := b.variant.(runtime.Type_Info_String);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
case Type_Info_Boolean:
|
case runtime.Type_Info_Boolean:
|
||||||
_, ok := b.variant.(Type_Info_Boolean);
|
_, ok := b.variant.(runtime.Type_Info_Boolean);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
case Type_Info_Any:
|
case runtime.Type_Info_Any:
|
||||||
_, ok := b.variant.(Type_Info_Any);
|
_, ok := b.variant.(runtime.Type_Info_Any);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
case Type_Info_Pointer:
|
case runtime.Type_Info_Pointer:
|
||||||
y, ok := b.variant.(Type_Info_Pointer);
|
y, ok := b.variant.(runtime.Type_Info_Pointer);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
return are_types_identical(x.elem, y.elem);
|
return are_types_identical(x.elem, y.elem);
|
||||||
|
|
||||||
case Type_Info_Procedure:
|
case runtime.Type_Info_Procedure:
|
||||||
y, ok := b.variant.(Type_Info_Procedure);
|
y, ok := b.variant.(runtime.Type_Info_Procedure);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
switch {
|
switch {
|
||||||
case x.variadic != y.variadic,
|
case x.variadic != y.variadic,
|
||||||
@@ -65,24 +67,24 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
|
|
||||||
return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results);
|
return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results);
|
||||||
|
|
||||||
case Type_Info_Array:
|
case runtime.Type_Info_Array:
|
||||||
y, ok := b.variant.(Type_Info_Array);
|
y, ok := b.variant.(runtime.Type_Info_Array);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
if x.count != y.count do return false;
|
if x.count != y.count do return false;
|
||||||
return are_types_identical(x.elem, y.elem);
|
return are_types_identical(x.elem, y.elem);
|
||||||
|
|
||||||
case Type_Info_Dynamic_Array:
|
case runtime.Type_Info_Dynamic_Array:
|
||||||
y, ok := b.variant.(Type_Info_Dynamic_Array);
|
y, ok := b.variant.(runtime.Type_Info_Dynamic_Array);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
return are_types_identical(x.elem, y.elem);
|
return are_types_identical(x.elem, y.elem);
|
||||||
|
|
||||||
case Type_Info_Slice:
|
case runtime.Type_Info_Slice:
|
||||||
y, ok := b.variant.(Type_Info_Slice);
|
y, ok := b.variant.(runtime.Type_Info_Slice);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
return are_types_identical(x.elem, y.elem);
|
return are_types_identical(x.elem, y.elem);
|
||||||
|
|
||||||
case Type_Info_Tuple:
|
case runtime.Type_Info_Tuple:
|
||||||
y, ok := b.variant.(Type_Info_Tuple);
|
y, ok := b.variant.(runtime.Type_Info_Tuple);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
if len(x.types) != len(y.types) do return false;
|
if len(x.types) != len(y.types) do return false;
|
||||||
for _, i in x.types {
|
for _, i in x.types {
|
||||||
@@ -93,8 +95,8 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Type_Info_Struct:
|
case runtime.Type_Info_Struct:
|
||||||
y, ok := b.variant.(Type_Info_Struct);
|
y, ok := b.variant.(runtime.Type_Info_Struct);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
switch {
|
switch {
|
||||||
case len(x.types) != len(y.types),
|
case len(x.types) != len(y.types),
|
||||||
@@ -112,8 +114,8 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Type_Info_Union:
|
case runtime.Type_Info_Union:
|
||||||
y, ok := b.variant.(Type_Info_Union);
|
y, ok := b.variant.(runtime.Type_Info_Union);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
if len(x.variants) != len(y.variants) do return false;
|
if len(x.variants) != len(y.variants) do return false;
|
||||||
|
|
||||||
@@ -123,17 +125,17 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Type_Info_Enum:
|
case runtime.Type_Info_Enum:
|
||||||
// NOTE(bill): Should be handled above
|
// NOTE(bill): Should be handled above
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case Type_Info_Map:
|
case runtime.Type_Info_Map:
|
||||||
y, ok := b.variant.(Type_Info_Map);
|
y, ok := b.variant.(runtime.Type_Info_Map);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value);
|
return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value);
|
||||||
|
|
||||||
case Type_Info_Bit_Field:
|
case runtime.Type_Info_Bit_Field:
|
||||||
y, ok := b.variant.(Type_Info_Bit_Field);
|
y, ok := b.variant.(runtime.Type_Info_Bit_Field);
|
||||||
if !ok do return false;
|
if !ok do return false;
|
||||||
if len(x.names) != len(y.names) do return false;
|
if len(x.names) != len(y.names) do return false;
|
||||||
|
|
||||||
@@ -154,101 +156,101 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
is_signed :: proc(info: ^Type_Info) -> bool {
|
is_signed :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
switch i in type_info_base(info).variant {
|
switch i in runtime.type_info_base(info).variant {
|
||||||
case Type_Info_Integer: return i.signed;
|
case runtime.Type_Info_Integer: return i.signed;
|
||||||
case Type_Info_Float: return true;
|
case runtime.Type_Info_Float: return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
is_integer :: proc(info: ^Type_Info) -> bool {
|
is_integer :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Integer);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Integer);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_rune :: proc(info: ^Type_Info) -> bool {
|
is_rune :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Rune);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Rune);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_float :: proc(info: ^Type_Info) -> bool {
|
is_float :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Float);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Float);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_complex :: proc(info: ^Type_Info) -> bool {
|
is_complex :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Complex);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Complex);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_any :: proc(info: ^Type_Info) -> bool {
|
is_any :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Any);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Any);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_string :: proc(info: ^Type_Info) -> bool {
|
is_string :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_String);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_String);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_boolean :: proc(info: ^Type_Info) -> bool {
|
is_boolean :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Boolean);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Boolean);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_pointer :: proc(info: ^Type_Info) -> bool {
|
is_pointer :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Pointer);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Pointer);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_procedure :: proc(info: ^Type_Info) -> bool {
|
is_procedure :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Procedure);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Procedure);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_array :: proc(info: ^Type_Info) -> bool {
|
is_array :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Array);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Array);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_dynamic_array :: proc(info: ^Type_Info) -> bool {
|
is_dynamic_array :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Dynamic_Array);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_dynamic_map :: proc(info: ^Type_Info) -> bool {
|
is_dynamic_map :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Map);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Map);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_slice :: proc(info: ^Type_Info) -> bool {
|
is_slice :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Slice);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Slice);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_tuple :: proc(info: ^Type_Info) -> bool {
|
is_tuple :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Tuple);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Tuple);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_struct :: proc(info: ^Type_Info) -> bool {
|
is_struct :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
s, ok := type_info_base(info).variant.(Type_Info_Struct);
|
s, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Struct);
|
||||||
return ok && !s.is_raw_union;
|
return ok && !s.is_raw_union;
|
||||||
}
|
}
|
||||||
is_raw_union :: proc(info: ^Type_Info) -> bool {
|
is_raw_union :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
s, ok := type_info_base(info).variant.(Type_Info_Struct);
|
s, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Struct);
|
||||||
return ok && s.is_raw_union;
|
return ok && s.is_raw_union;
|
||||||
}
|
}
|
||||||
is_union :: proc(info: ^Type_Info) -> bool {
|
is_union :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Union);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Union);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_enum :: proc(info: ^Type_Info) -> bool {
|
is_enum :: proc(info: ^runtime.Type_Info) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).variant.(Type_Info_Enum);
|
_, ok := runtime.type_info_base(info).variant.(runtime.Type_Info_Enum);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import "core:hash"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:raw"
|
|
||||||
import "core:sort"
|
import "core:sort"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:types"
|
import "core:types"
|
||||||
import "core:unicode/utf16"
|
import "core:unicode/utf16"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
import "core:runtime"
|
||||||
|
|
||||||
when os.OS == "windows" {
|
when os.OS == "windows" {
|
||||||
import "core:atomics"
|
import "core:atomics"
|
||||||
@@ -352,7 +352,7 @@ parametric_polymorphism :: proc() {
|
|||||||
TABLE_SIZE_MIN :: 32;
|
TABLE_SIZE_MIN :: 32;
|
||||||
Table :: struct(Key, Value: type) {
|
Table :: struct(Key, Value: type) {
|
||||||
count: int,
|
count: int,
|
||||||
allocator: Allocator,
|
allocator: mem.Allocator,
|
||||||
slots: []Table_Slot(Key, Value),
|
slots: []Table_Slot(Key, Value),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,12 +495,12 @@ threading_example :: proc() {
|
|||||||
fmt.println("# threading_example");
|
fmt.println("# threading_example");
|
||||||
|
|
||||||
unordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
|
unordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
|
||||||
__bounds_check_error_loc(loc, index, len(array));
|
runtime.bounds_check_error_loc(loc, index, len(array));
|
||||||
array[index] = array[len(array)-1];
|
array[index] = array[len(array)-1];
|
||||||
pop(array);
|
pop(array);
|
||||||
}
|
}
|
||||||
ordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
|
ordered_remove :: proc(array: ^[dynamic]$T, index: int, loc := #caller_location) {
|
||||||
__bounds_check_error_loc(loc, index, len(array));
|
runtime.bounds_check_error_loc(loc, index, len(array));
|
||||||
copy(array[index..], array[index+1..]);
|
copy(array[index..], array[index+1..]);
|
||||||
pop(array);
|
pop(array);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -4125,7 +4125,6 @@ void check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count,
|
|||||||
o.mode = Addressing_Invalid;
|
o.mode = Addressing_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (o.type == nullptr || o.type->kind != Type_Tuple) {
|
if (o.type == nullptr || o.type->kind != Type_Tuple) {
|
||||||
if (allow_ok && lhs_count == 2 && rhs.count == 1 &&
|
if (allow_ok && lhs_count == 2 && rhs.count == 1 &&
|
||||||
(o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) {
|
(o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) {
|
||||||
@@ -5913,7 +5912,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, AstNode *node,
|
|||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_package_dependency(c, "runtime", "__type_assertion_check");
|
add_package_dependency(c, "runtime", "type_assertion_check");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(tc, TypeCast, node);
|
case_ast_node(tc, TypeCast, node);
|
||||||
@@ -6218,8 +6217,8 @@ ExprKind check_expr_base(CheckerContext *c, Operand *o, AstNode *node, Type *typ
|
|||||||
type = nullptr;
|
type = nullptr;
|
||||||
break;
|
break;
|
||||||
case Addressing_Constant:
|
case Addressing_Constant:
|
||||||
type = o->type;
|
|
||||||
value = o->value;
|
value = o->value;
|
||||||
|
type = o->type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
type = o->type;
|
type = o->type;
|
||||||
|
|||||||
+106
-55
@@ -272,7 +272,6 @@ Scope *create_scope_from_package(CheckerContext *c, AstPackage *p) {
|
|||||||
|
|
||||||
if (p->kind == Package_Runtime) {
|
if (p->kind == Package_Runtime) {
|
||||||
s->is_global = true;
|
s->is_global = true;
|
||||||
universal_scope->shared = s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->is_init || s->is_global) {
|
if (s->is_init || s->is_global) {
|
||||||
@@ -377,31 +376,7 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
|
|||||||
|
|
||||||
if (s->is_proc) {
|
if (s->is_proc) {
|
||||||
gone_thru_proc = true;
|
gone_thru_proc = true;
|
||||||
} else if (s->shared) {
|
|
||||||
Entity **found = map_get(&s->shared->elements, key);
|
|
||||||
if (found) {
|
|
||||||
Entity *e = *found;
|
|
||||||
if (e->kind == Entity_Variable &&
|
|
||||||
!e->scope->is_file) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e->scope->parent != s->shared) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((e->kind == Entity_ImportName ||
|
|
||||||
e->kind == Entity_LibraryName)
|
|
||||||
&& gone_thru_package) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity_) *entity_ = e;
|
|
||||||
if (scope_) *scope_ = s->shared;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->is_package) {
|
if (s->is_package) {
|
||||||
gone_thru_package = true;
|
gone_thru_package = true;
|
||||||
}
|
}
|
||||||
@@ -511,7 +486,7 @@ void add_package_dependency(CheckerContext *c, char *package_name, char *name) {
|
|||||||
String n = make_string_c(name);
|
String n = make_string_c(name);
|
||||||
AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name));
|
AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name));
|
||||||
Entity *e = scope_lookup_entity(p->scope, n);
|
Entity *e = scope_lookup_entity(p->scope, n);
|
||||||
GB_ASSERT(e != nullptr);
|
GB_ASSERT_MSG(e != nullptr, "%s", name);
|
||||||
ptr_set_add(&c->decl->deps, e);
|
ptr_set_add(&c->decl->deps, e);
|
||||||
// add_type_info_type(c, e->type);
|
// add_type_info_type(c, e->type);
|
||||||
}
|
}
|
||||||
@@ -841,7 +816,7 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mode == Addressing_Constant && type == t_invalid) {
|
if (mode == Addressing_Constant && type == t_invalid) {
|
||||||
compiler_error("add_type_and_value - invalid type: %s", type_to_string(type));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeAndValue tv = {};
|
TypeAndValue tv = {};
|
||||||
@@ -939,20 +914,11 @@ void add_entity_and_decl_info(CheckerContext *c, AstNode *identifier, Entity *e,
|
|||||||
|
|
||||||
if (e->scope != nullptr) {
|
if (e->scope != nullptr) {
|
||||||
Scope *scope = e->scope;
|
Scope *scope = e->scope;
|
||||||
if (scope->is_file) {
|
if (scope->is_file && is_entity_kind_exported(e->kind)) {
|
||||||
switch (e->kind) {
|
AstPackage *pkg = scope->file->pkg;
|
||||||
case Entity_ImportName:
|
GB_ASSERT(pkg->scope == scope->parent);
|
||||||
case Entity_LibraryName:
|
GB_ASSERT(c->pkg == pkg);
|
||||||
// NOTE(bill): Entities local to file rather than package
|
scope = pkg->scope;
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
AstPackage *pkg = scope->file->pkg;
|
|
||||||
GB_ASSERT(pkg->scope == scope->parent);
|
|
||||||
GB_ASSERT(c->pkg == pkg);
|
|
||||||
scope = pkg->scope;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
add_entity(c->checker, scope, identifier, e);
|
add_entity(c->checker, scope, identifier, e);
|
||||||
}
|
}
|
||||||
@@ -1346,12 +1312,11 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
|||||||
String required_builtin_entities[] = {
|
String required_builtin_entities[] = {
|
||||||
str_lit("__init_context"),
|
str_lit("__init_context"),
|
||||||
|
|
||||||
str_lit("__args__"),
|
str_lit("args__"),
|
||||||
str_lit("__type_table"),
|
str_lit("type_table"),
|
||||||
|
|
||||||
str_lit("Type_Info"),
|
str_lit("Type_Info"),
|
||||||
str_lit("Source_Code_Location"),
|
str_lit("Source_Code_Location"),
|
||||||
str_lit("Allocator"),
|
|
||||||
str_lit("Context"),
|
str_lit("Context"),
|
||||||
};
|
};
|
||||||
for (isize i = 0; i < gb_count_of(required_builtin_entities); i++) {
|
for (isize i = 0; i < gb_count_of(required_builtin_entities); i++) {
|
||||||
@@ -1360,18 +1325,27 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
|||||||
|
|
||||||
AstPackage *mem = get_core_package(&c->info, str_lit("mem"));
|
AstPackage *mem = get_core_package(&c->info, str_lit("mem"));
|
||||||
String required_mem_entities[] = {
|
String required_mem_entities[] = {
|
||||||
str_lit("default_allocator"),
|
|
||||||
str_lit("zero"),
|
str_lit("zero"),
|
||||||
|
str_lit("Allocator"),
|
||||||
};
|
};
|
||||||
for (isize i = 0; i < gb_count_of(required_mem_entities); i++) {
|
for (isize i = 0; i < gb_count_of(required_mem_entities); i++) {
|
||||||
add_dependency_to_set(c, scope_lookup_entity(mem->scope, required_mem_entities[i]));
|
add_dependency_to_set(c, scope_lookup_entity(mem->scope, required_mem_entities[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstPackage *os = get_core_package(&c->info, str_lit("os"));
|
||||||
|
String required_os_entities[] = {
|
||||||
|
str_lit("default_allocator"),
|
||||||
|
};
|
||||||
|
for (isize i = 0; i < gb_count_of(required_os_entities); i++) {
|
||||||
|
add_dependency_to_set(c, scope_lookup_entity(os->scope, required_mem_entities[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!build_context.no_bounds_check) {
|
if (!build_context.no_bounds_check) {
|
||||||
String bounds_check_entities[] = {
|
String bounds_check_entities[] = {
|
||||||
str_lit("__bounds_check_error"),
|
str_lit("bounds_check_error"),
|
||||||
str_lit("__slice_expr_error"),
|
str_lit("slice_expr_error"),
|
||||||
str_lit("__dynamic_array_expr_error"),
|
str_lit("dynamic_array_expr_error"),
|
||||||
};
|
};
|
||||||
for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) {
|
for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) {
|
||||||
add_dependency_to_set(c, scope_lookup_entity(c->info.runtime_package->scope, bounds_check_entities[i]));
|
add_dependency_to_set(c, scope_lookup_entity(c->info.runtime_package->scope, bounds_check_entities[i]));
|
||||||
@@ -1497,7 +1471,7 @@ Entity *find_core_entity(Checker *c, String name) {
|
|||||||
Entity *e = current_scope_lookup_entity(c->info.runtime_package->scope, name);
|
Entity *e = current_scope_lookup_entity(c->info.runtime_package->scope, name);
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
compiler_error("Could not find type declaration for '%.*s'\n"
|
compiler_error("Could not find type declaration for '%.*s'\n"
|
||||||
"Is '_preload.odin' missing from the 'core' directory relative to odin.exe?", LIT(name));
|
, LIT(name));
|
||||||
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
@@ -1507,7 +1481,7 @@ Type *find_core_type(Checker *c, String name) {
|
|||||||
Entity *e = current_scope_lookup_entity(c->info.runtime_package->scope, name);
|
Entity *e = current_scope_lookup_entity(c->info.runtime_package->scope, name);
|
||||||
if (e == nullptr) {
|
if (e == nullptr) {
|
||||||
compiler_error("Could not find type declaration for '%.*s'\n"
|
compiler_error("Could not find type declaration for '%.*s'\n"
|
||||||
"Is '_preload.odin' missing from the 'core' directory relative to odin.exe?", LIT(name));
|
, LIT(name));
|
||||||
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
||||||
}
|
}
|
||||||
return e->type;
|
return e->type;
|
||||||
@@ -1624,7 +1598,16 @@ void init_core_allocator(Checker *c) {
|
|||||||
if (t_allocator != nullptr) {
|
if (t_allocator != nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t_allocator = find_core_type(c, str_lit("Allocator"));
|
AstPackage *pkg = get_core_package(&c->info, str_lit("mem"));
|
||||||
|
|
||||||
|
String name = str_lit("Allocator");
|
||||||
|
Entity *e = current_scope_lookup_entity(pkg->scope, name);
|
||||||
|
if (e == nullptr) {
|
||||||
|
compiler_error("Could not find type declaration for '%.*s'\n", LIT(name));
|
||||||
|
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
||||||
|
}
|
||||||
|
|
||||||
|
t_allocator = e->type;
|
||||||
t_allocator_ptr = alloc_type_pointer(t_allocator);
|
t_allocator_ptr = alloc_type_pointer(t_allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1646,11 +1629,11 @@ void init_core_source_code_location(Checker *c) {
|
|||||||
|
|
||||||
void init_core_map_type(Checker *c) {
|
void init_core_map_type(Checker *c) {
|
||||||
if (t_map_key == nullptr) {
|
if (t_map_key == nullptr) {
|
||||||
t_map_key = find_core_type(c, str_lit("__Map_Key"));
|
t_map_key = find_core_type(c, str_lit("Map_Key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t_map_header == nullptr) {
|
if (t_map_header == nullptr) {
|
||||||
t_map_header = find_core_type(c, str_lit("__Map_Header"));
|
t_map_header = find_core_type(c, str_lit("Map_Header"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1767,7 +1750,8 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
|||||||
ac->thread_local_model = str_lit("default");
|
ac->thread_local_model = str_lit("default");
|
||||||
} else if (value.kind == ExactValue_String) {
|
} else if (value.kind == ExactValue_String) {
|
||||||
String model = value.value_string;
|
String model = value.value_string;
|
||||||
if (model == "localdynamic" ||
|
if (model == "default" ||
|
||||||
|
model == "localdynamic" ||
|
||||||
model == "initialexec" ||
|
model == "initialexec" ||
|
||||||
model == "localexec") {
|
model == "localexec") {
|
||||||
ac->thread_local_model = model;
|
ac->thread_local_model = model;
|
||||||
@@ -1935,6 +1919,66 @@ void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *w
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<AstNode *> *attributes) {
|
||||||
|
switch (e->kind) {
|
||||||
|
case Entity_ProcGroup:
|
||||||
|
case Entity_Procedure:
|
||||||
|
case Entity_TypeName:
|
||||||
|
// Okay
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(ctx->scope->is_file && ctx->scope->file->pkg->kind == Package_Runtime)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_array(j, *attributes) {
|
||||||
|
AstNode *attr = (*attributes)[j];
|
||||||
|
if (attr->kind != AstNode_Attribute) continue;
|
||||||
|
for (isize k = 0; k < attr->Attribute.elems.count; k++) {
|
||||||
|
AstNode *elem = attr->Attribute.elems[k];
|
||||||
|
String name = {};
|
||||||
|
AstNode *value = nullptr;
|
||||||
|
|
||||||
|
switch (elem->kind) {
|
||||||
|
case_ast_node(i, Ident, elem);
|
||||||
|
name = i->token.string;
|
||||||
|
case_end;
|
||||||
|
case_ast_node(fv, FieldValue, elem);
|
||||||
|
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
||||||
|
name = fv->field->Ident.token.string;
|
||||||
|
value = fv->value;
|
||||||
|
case_end;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "builtin") {
|
||||||
|
add_entity(ctx->checker, universal_scope, nullptr, e);
|
||||||
|
GB_ASSERT(scope_lookup_entity(universal_scope, e->token.string) != nullptr);
|
||||||
|
if (value != nullptr) {
|
||||||
|
error(value, "'builtin' cannot have a field value");
|
||||||
|
}
|
||||||
|
// Remove the builtin tag
|
||||||
|
attr->Attribute.elems[k] = attr->Attribute.elems[attr->Attribute.elems.count-1];
|
||||||
|
attr->Attribute.elems.count -= 1;
|
||||||
|
k--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (isize i = 0; i < attributes->count; i++) {
|
||||||
|
AstNode *attr = (*attributes)[i];
|
||||||
|
if (attr->kind != AstNode_Attribute) continue;
|
||||||
|
if (attr->Attribute.elems.count == 0) {
|
||||||
|
(*attributes)[i] = (*attributes)[attributes->count-1];
|
||||||
|
attributes->count--;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
||||||
ast_node(vd, ValueDecl, decl);
|
ast_node(vd, ValueDecl, decl);
|
||||||
|
|
||||||
@@ -2093,6 +2137,7 @@ void check_collect_value_decl(CheckerContext *c, AstNode *decl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_builtin_attributes(c, e, &d->attributes);
|
||||||
|
|
||||||
add_entity_and_decl_info(c, name, e, d);
|
add_entity_and_decl_info(c, name, e, d);
|
||||||
}
|
}
|
||||||
@@ -2446,6 +2491,11 @@ Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start, AstPackage
|
|||||||
}
|
}
|
||||||
GB_ASSERT(pkg != nullptr && pkg->scope != nullptr);
|
GB_ASSERT(pkg != nullptr && pkg->scope != nullptr);
|
||||||
|
|
||||||
|
if (pkg->kind == Package_Runtime) {
|
||||||
|
// NOTE(bill): Allow cyclic imports within the runtime package for the time being
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ImportPathItem item = {pkg, decl};
|
ImportPathItem item = {pkg, decl};
|
||||||
if (pkg == end) {
|
if (pkg == end) {
|
||||||
auto path = array_make<ImportPathItem>(heap_allocator());
|
auto path = array_make<ImportPathItem>(heap_allocator());
|
||||||
@@ -2821,6 +2871,7 @@ void check_import_entities(Checker *c) {
|
|||||||
return item.pkg->name;
|
return item.pkg->name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 1
|
||||||
if (path.count == 1) {
|
if (path.count == 1) {
|
||||||
// TODO(bill): Should this be allowed or disabled?
|
// TODO(bill): Should this be allowed or disabled?
|
||||||
#if 0
|
#if 0
|
||||||
@@ -2839,12 +2890,12 @@ void check_import_entities(Checker *c) {
|
|||||||
}
|
}
|
||||||
error(item.decl, "'%.*s'", LIT(pkg_name));
|
error(item.decl, "'%.*s'", LIT(pkg_name));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, n->pred.entries) {
|
for_array(i, n->pred.entries) {
|
||||||
ImportGraphNode *p = n->pred.entries[i].ptr;
|
ImportGraphNode *p = n->pred.entries[i].ptr;
|
||||||
p->dep_count = gb_max(p->dep_count-1, 0);
|
p->dep_count = gb_max(p->dep_count-1, 0);
|
||||||
// p->dep_count -= 1;
|
|
||||||
priority_queue_fix(&pq, p->index);
|
priority_queue_fix(&pq, p->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-20
@@ -7,6 +7,7 @@ struct DeclInfo;
|
|||||||
struct AstFile;
|
struct AstFile;
|
||||||
struct Checker;
|
struct Checker;
|
||||||
struct CheckerInfo;
|
struct CheckerInfo;
|
||||||
|
struct CheckerContext;
|
||||||
|
|
||||||
enum AddressingMode {
|
enum AddressingMode {
|
||||||
Addressing_Invalid, // invalid addressing mode
|
Addressing_Invalid, // invalid addressing mode
|
||||||
@@ -177,6 +178,26 @@ struct BlockLabel {
|
|||||||
AstNode *label; // AstNode_Label;
|
AstNode *label; // AstNode_Label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AttributeContext {
|
||||||
|
String link_name;
|
||||||
|
String link_prefix;
|
||||||
|
isize init_expr_list_count;
|
||||||
|
String thread_local_model;
|
||||||
|
String deprecated_message;
|
||||||
|
};
|
||||||
|
|
||||||
|
AttributeContext make_attribute_context(String link_prefix) {
|
||||||
|
AttributeContext ac = {};
|
||||||
|
ac.link_prefix = link_prefix;
|
||||||
|
return ac;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECL_ATTRIBUTE_PROC(_name) bool _name(CheckerContext *c, AstNode *elem, String name, ExactValue value, AttributeContext *ac)
|
||||||
|
typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
|
||||||
|
|
||||||
|
void check_decl_attributes(CheckerContext *c, Array<AstNode *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac);
|
||||||
|
|
||||||
|
|
||||||
// DeclInfo is used to store information of certain declarations to allow for "any order" usage
|
// DeclInfo is used to store information of certain declarations to allow for "any order" usage
|
||||||
struct DeclInfo {
|
struct DeclInfo {
|
||||||
DeclInfo * parent; // NOTE(bill): only used for procedure literals at the moment
|
DeclInfo * parent; // NOTE(bill): only used for procedure literals at the moment
|
||||||
@@ -218,7 +239,7 @@ struct Scope {
|
|||||||
Scope * last_child;
|
Scope * last_child;
|
||||||
Map<Entity *> elements; // Key: String
|
Map<Entity *> elements; // Key: String
|
||||||
PtrSet<Entity *> implicit;
|
PtrSet<Entity *> implicit;
|
||||||
Scope * shared;
|
// Scope * shared;
|
||||||
|
|
||||||
Array<AstNode *> delayed_directives;
|
Array<AstNode *> delayed_directives;
|
||||||
Array<AstNode *> delayed_imports;
|
Array<AstNode *> delayed_imports;
|
||||||
@@ -392,25 +413,6 @@ void check_collect_entities(CheckerContext *c, Array<AstNode *> const &nodes);
|
|||||||
void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *ws);
|
void check_collect_entities_from_when_stmt(CheckerContext *c, AstNodeWhenStmt *ws);
|
||||||
void check_delayed_file_import_entity(CheckerContext *c, AstNode *decl);
|
void check_delayed_file_import_entity(CheckerContext *c, AstNode *decl);
|
||||||
|
|
||||||
struct AttributeContext {
|
|
||||||
String link_name;
|
|
||||||
String link_prefix;
|
|
||||||
isize init_expr_list_count;
|
|
||||||
String thread_local_model;
|
|
||||||
String deprecated_message;
|
|
||||||
};
|
|
||||||
|
|
||||||
AttributeContext make_attribute_context(String link_prefix) {
|
|
||||||
AttributeContext ac = {};
|
|
||||||
ac.link_prefix = link_prefix;
|
|
||||||
return ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECL_ATTRIBUTE_PROC(_name) bool _name(CheckerContext *c, AstNode *elem, String name, ExactValue value, AttributeContext *ac)
|
|
||||||
typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
|
|
||||||
|
|
||||||
void check_decl_attributes(CheckerContext *c, Array<AstNode *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac);
|
|
||||||
|
|
||||||
CheckerTypePath *new_checker_type_path();
|
CheckerTypePath *new_checker_type_path();
|
||||||
void destroy_checker_type_path(CheckerTypePath *tp);
|
void destroy_checker_type_path(CheckerTypePath *tp);
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -40,13 +40,13 @@ GB_ALLOCATOR_PROC(heap_allocator_proc);
|
|||||||
gbAllocator heap_allocator(void) {
|
gbAllocator heap_allocator(void) {
|
||||||
gbAllocator a;
|
gbAllocator a;
|
||||||
a.proc = heap_allocator_proc;
|
a.proc = heap_allocator_proc;
|
||||||
a.data = NULL;
|
a.data = nullptr;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GB_ALLOCATOR_PROC(heap_allocator_proc) {
|
GB_ALLOCATOR_PROC(heap_allocator_proc) {
|
||||||
void *ptr = NULL;
|
void *ptr = nullptr;
|
||||||
gb_unused(allocator_data);
|
gb_unused(allocator_data);
|
||||||
gb_unused(old_size);
|
gb_unused(old_size);
|
||||||
|
|
||||||
@@ -348,7 +348,7 @@ void *pool_alloc(Pool *pool, isize size, isize align) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GB_ALLOCATOR_PROC(pool_allocator_proc) {
|
GB_ALLOCATOR_PROC(pool_allocator_proc) {
|
||||||
void *ptr = NULL;
|
void *ptr = nullptr;
|
||||||
Pool *pool = cast(Pool *)allocator_data;
|
Pool *pool = cast(Pool *)allocator_data;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+51
-51
@@ -1534,7 +1534,7 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String na
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
irValue *ir_emit_global_call (irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr = nullptr);
|
irValue *ir_emit_runtime_call (irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr = nullptr);
|
||||||
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, AstNode *expr = nullptr);
|
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, AstNode *expr = nullptr);
|
||||||
|
|
||||||
|
|
||||||
@@ -1593,7 +1593,7 @@ void ir_emit_init_context(irProcedure *proc, irValue *c = nullptr) {
|
|||||||
gbAllocator a = m->allocator;
|
gbAllocator a = m->allocator;
|
||||||
auto args = array_make<irValue *>(a, 1);
|
auto args = array_make<irValue *>(a, 1);
|
||||||
args[0] = c ? c : m->global_default_context;
|
args[0] = c ? c : m->global_default_context;
|
||||||
ir_emit_global_call(proc, "__init_context", args);
|
ir_emit_runtime_call(proc, "__init_context", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1637,7 +1637,7 @@ irValue *ir_find_or_generate_context_ptr(irProcedure *proc) {
|
|||||||
|
|
||||||
irValue *ep = ir_emit_struct_ep(proc, c, 0);
|
irValue *ep = ir_emit_struct_ep(proc, c, 0);
|
||||||
Array<irValue *> args = {};
|
Array<irValue *> args = {};
|
||||||
irValue *v = ir_emit_package_call(proc, "mem", "default_allocator", args);
|
irValue *v = ir_emit_package_call(proc, "os", "default_allocator", args);
|
||||||
ir_emit_store(proc, ep, v);
|
ir_emit_store(proc, ep, v);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
@@ -1702,7 +1702,7 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_emit_global_call(irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr) {
|
irValue *ir_emit_runtime_call(irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr) {
|
||||||
String name = make_string_c(cast(char *)name_);
|
String name = make_string_c(cast(char *)name_);
|
||||||
|
|
||||||
AstPackage *p = proc->module->info->runtime_package;
|
AstPackage *p = proc->module->info->runtime_package;
|
||||||
@@ -1879,7 +1879,7 @@ irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
|
|||||||
} else {
|
} else {
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = str;
|
args[0] = str;
|
||||||
hashed_str = ir_emit_global_call(proc, "__default_hash_string", args);
|
hashed_str = ir_emit_runtime_call(proc, "__default_hash_string", args);
|
||||||
}
|
}
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), hashed_str);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), hashed_str);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), str);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), str);
|
||||||
@@ -1941,7 +1941,7 @@ irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, T
|
|||||||
args[1] = key;
|
args[1] = key;
|
||||||
args[2] = ir_emit_conv(proc, ptr, t_rawptr);
|
args[2] = ir_emit_conv(proc, ptr, t_rawptr);
|
||||||
args[3] = ir_emit_source_code_location(proc, nullptr);
|
args[3] = ir_emit_source_code_location(proc, nullptr);
|
||||||
return ir_emit_global_call(proc, "__dynamic_map_set", args);
|
return ir_emit_runtime_call(proc, "__dynamic_map_set", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2041,7 +2041,7 @@ irValue *ir_addr_load(irProcedure *proc, irAddr const &addr) {
|
|||||||
args[0] = h;
|
args[0] = h;
|
||||||
args[1] = key;
|
args[1] = key;
|
||||||
|
|
||||||
irValue *ptr = ir_emit_global_call(proc, "__dynamic_map_get", args);
|
irValue *ptr = ir_emit_runtime_call(proc, "__dynamic_map_get", args);
|
||||||
irValue *ok = ir_emit_conv(proc, ir_emit_comp(proc, Token_NotEq, ptr, v_raw_nil), t_bool);
|
irValue *ok = ir_emit_conv(proc, ir_emit_comp(proc, Token_NotEq, ptr, v_raw_nil), t_bool);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), ok);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), ok);
|
||||||
|
|
||||||
@@ -2543,7 +2543,7 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
|||||||
auto args = array_make<irValue *>(proc->module->allocator, 2);
|
auto args = array_make<irValue *>(proc->module->allocator, 2);
|
||||||
args[0] = left;
|
args[0] = left;
|
||||||
args[1] = right;
|
args[1] = right;
|
||||||
return ir_emit_global_call(proc, runtime_proc, args);
|
return ir_emit_runtime_call(proc, runtime_proc, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type_complex(a)) {
|
if (is_type_complex(a)) {
|
||||||
@@ -2568,7 +2568,7 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal
|
|||||||
auto args = array_make<irValue *>(proc->module->allocator, 2);
|
auto args = array_make<irValue *>(proc->module->allocator, 2);
|
||||||
args[0] = left;
|
args[0] = left;
|
||||||
args[1] = right;
|
args[1] = right;
|
||||||
return ir_emit_global_call(proc, runtime_proc, args);
|
return ir_emit_runtime_call(proc, runtime_proc, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2893,7 +2893,7 @@ irValue *ir_cstring_len(irProcedure *proc, irValue *value) {
|
|||||||
GB_ASSERT(is_type_cstring(ir_type(value)));
|
GB_ASSERT(is_type_cstring(ir_type(value)));
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = ir_emit_conv(proc, value, t_cstring);
|
args[0] = ir_emit_conv(proc, value, t_cstring);
|
||||||
return ir_emit_global_call(proc, "__cstring_len", args);
|
return ir_emit_runtime_call(proc, "__cstring_len", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3140,7 +3140,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
irValue *c = ir_emit_conv(proc, value, t_cstring);
|
irValue *c = ir_emit_conv(proc, value, t_cstring);
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = c;
|
args[0] = c;
|
||||||
irValue *s = ir_emit_global_call(proc, "__cstring_to_string", args);
|
irValue *s = ir_emit_runtime_call(proc, "__cstring_to_string", args);
|
||||||
return ir_emit_conv(proc, s, dst);
|
return ir_emit_conv(proc, s, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3161,13 +3161,13 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
// case 4: {
|
// case 4: {
|
||||||
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
// args[0] = value;
|
// args[0] = value;
|
||||||
// return ir_emit_global_call(proc, "__gnu_h2f_ieee", args);
|
// return ir_emit_runtime_call(proc, "__gnu_h2f_ieee", args);
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// case 8: {
|
// case 8: {
|
||||||
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
// args[0] = value;
|
// args[0] = value;
|
||||||
// return ir_emit_global_call(proc, "__f16_to_f64", args);
|
// return ir_emit_runtime_call(proc, "__f16_to_f64", args);
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
@@ -3177,13 +3177,13 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
// case 4: {
|
// case 4: {
|
||||||
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
// args[0] = value;
|
// args[0] = value;
|
||||||
// return ir_emit_global_call(proc, "__gnu_f2h_ieee", args);
|
// return ir_emit_runtime_call(proc, "__gnu_f2h_ieee", args);
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// case 8: {
|
// case 8: {
|
||||||
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
// auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
// args[0] = value;
|
// args[0] = value;
|
||||||
// return ir_emit_global_call(proc, "__truncdfhf2", args);
|
// return ir_emit_runtime_call(proc, "__truncdfhf2", args);
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
@@ -3509,7 +3509,7 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
|||||||
|
|
||||||
args[4] = ir_typeid(proc->module, src_type);
|
args[4] = ir_typeid(proc->module, src_type);
|
||||||
args[5] = ir_typeid(proc->module, dst_type);
|
args[5] = ir_typeid(proc->module, dst_type);
|
||||||
ir_emit_global_call(proc, "__type_assertion_check", args);
|
ir_emit_runtime_call(proc, "type_assertion_check", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ir_emit_load(proc, ir_emit_struct_ep(proc, v, 0));
|
return ir_emit_load(proc, ir_emit_struct_ep(proc, v, 0));
|
||||||
@@ -3569,7 +3569,7 @@ irAddr ir_emit_any_cast_addr(irProcedure *proc, irValue *value, Type *type, Toke
|
|||||||
|
|
||||||
args[4] = any_typeid;
|
args[4] = any_typeid;
|
||||||
args[5] = dst_typeid;
|
args[5] = dst_typeid;
|
||||||
ir_emit_global_call(proc, "__type_assertion_check", args);
|
ir_emit_runtime_call(proc, "type_assertion_check", args);
|
||||||
|
|
||||||
return ir_addr(ir_emit_struct_ep(proc, v, 0));
|
return ir_addr(ir_emit_struct_ep(proc, v, 0));
|
||||||
}
|
}
|
||||||
@@ -3713,7 +3713,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu
|
|||||||
args[3] = index;
|
args[3] = index;
|
||||||
args[4] = len;
|
args[4] = len;
|
||||||
|
|
||||||
ir_emit_global_call(proc, "__bounds_check_error", args);
|
ir_emit_runtime_call(proc, "bounds_check_error", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *len, bool is_substring) {
|
void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *len, bool is_substring) {
|
||||||
@@ -3739,7 +3739,7 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir
|
|||||||
args[4] = high;
|
args[4] = high;
|
||||||
args[5] = len;
|
args[5] = len;
|
||||||
|
|
||||||
ir_emit_global_call(proc, "__slice_expr_error", args);
|
ir_emit_runtime_call(proc, "slice_expr_error", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max) {
|
void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max) {
|
||||||
@@ -3765,7 +3765,7 @@ void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue
|
|||||||
args[4] = high;
|
args[4] = high;
|
||||||
args[5] = max;
|
args[5] = max;
|
||||||
|
|
||||||
ir_emit_global_call(proc, "__dynamic_array_expr_error", args);
|
ir_emit_runtime_call(proc, "dynamic_array_expr_error", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4062,8 +4062,8 @@ irValue *ir_emit_min(irProcedure *proc, Type *t, irValue *x, irValue *y) {
|
|||||||
args[0] = x;
|
args[0] = x;
|
||||||
args[1] = y;
|
args[1] = y;
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
case 32: return ir_emit_global_call(proc, "__min_f32", args);
|
case 32: return ir_emit_runtime_call(proc, "__min_f32", args);
|
||||||
case 64: return ir_emit_global_call(proc, "__min_f64", args);
|
case 64: return ir_emit_runtime_call(proc, "__min_f64", args);
|
||||||
}
|
}
|
||||||
GB_PANIC("Unknown float type");
|
GB_PANIC("Unknown float type");
|
||||||
}
|
}
|
||||||
@@ -4080,8 +4080,8 @@ irValue *ir_emit_max(irProcedure *proc, Type *t, irValue *x, irValue *y) {
|
|||||||
args[0] = x;
|
args[0] = x;
|
||||||
args[1] = y;
|
args[1] = y;
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
case 32: return ir_emit_global_call(proc, "__max_f32", args);
|
case 32: return ir_emit_runtime_call(proc, "__max_f32", args);
|
||||||
case 64: return ir_emit_global_call(proc, "__max_f64", args);
|
case 64: return ir_emit_runtime_call(proc, "__max_f64", args);
|
||||||
}
|
}
|
||||||
GB_PANIC("Unknown float type");
|
GB_PANIC("Unknown float type");
|
||||||
}
|
}
|
||||||
@@ -4221,7 +4221,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
|
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = ir_build_expr(proc, arg);
|
args[0] = ir_build_expr(proc, arg);
|
||||||
return ir_emit_global_call(proc, "__type_info_of", args);
|
return ir_emit_runtime_call(proc, "__type_info_of", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_typeid_of: {
|
case BuiltinProc_typeid_of: {
|
||||||
@@ -4236,7 +4236,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
|
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = ir_emit_conv(proc, ir_build_expr(proc, arg), t_type_info_ptr);
|
args[0] = ir_emit_conv(proc, ir_build_expr(proc, arg), t_type_info_ptr);
|
||||||
return ir_emit_global_call(proc, "__typeid_of", args);
|
return ir_emit_runtime_call(proc, "__typeid_of", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_len: {
|
case BuiltinProc_len: {
|
||||||
@@ -4315,7 +4315,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
irValue **args = gb_alloc_array(a, irValue *, 2);
|
irValue **args = gb_alloc_array(a, irValue *, 2);
|
||||||
args[0] = ir_const_int(a, size);
|
args[0] = ir_const_int(a, size);
|
||||||
args[1] = ir_const_int(a, align);
|
args[1] = ir_const_int(a, align);
|
||||||
irValue *call = ir_emit_global_call(proc, "alloc", args, 2);
|
irValue *call = ir_emit_runtime_call(proc, "alloc", args, 2);
|
||||||
irValue *v = ir_emit_conv(proc, call, ptr_type);
|
irValue *v = ir_emit_conv(proc, call, ptr_type);
|
||||||
if (type != allocation_type) {
|
if (type != allocation_type) {
|
||||||
Type *u = base_type(allocation_type);
|
Type *u = base_type(allocation_type);
|
||||||
@@ -4387,7 +4387,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
args[0] = header;
|
args[0] = header;
|
||||||
args[1] = cap;
|
args[1] = cap;
|
||||||
args[2] = ir_emit_source_code_location(proc, ce->args[0]);
|
args[2] = ir_emit_source_code_location(proc, ce->args[0]);
|
||||||
ir_emit_global_call(proc, "__dynamic_map_reserve", args);
|
ir_emit_runtime_call(proc, "__dynamic_map_reserve", args);
|
||||||
|
|
||||||
return ir_emit_load(proc, map);
|
return ir_emit_load(proc, map);
|
||||||
} else if (is_type_dynamic_array(type)) {
|
} else if (is_type_dynamic_array(type)) {
|
||||||
@@ -4412,7 +4412,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
args[3] = len;
|
args[3] = len;
|
||||||
args[4] = cap;
|
args[4] = cap;
|
||||||
args[5] = ir_emit_source_code_location(proc, ce->args[0]);
|
args[5] = ir_emit_source_code_location(proc, ce->args[0]);
|
||||||
ir_emit_global_call(proc, "__dynamic_array_make", args);
|
ir_emit_runtime_call(proc, "__dynamic_array_make", args);
|
||||||
return ir_emit_load(proc, array);
|
return ir_emit_load(proc, array);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4438,7 +4438,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||||
args[0] = da_allocator;
|
args[0] = da_allocator;
|
||||||
args[1] = ptr;
|
args[1] = ptr;
|
||||||
return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
return ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
|
||||||
} else if (is_type_map(type)) {
|
} else if (is_type_map(type)) {
|
||||||
irValue *map = ir_build_expr(proc, node);
|
irValue *map = ir_build_expr(proc, node);
|
||||||
irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map);
|
irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map);
|
||||||
@@ -4453,7 +4453,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||||
args[0] = da_allocator;
|
args[0] = da_allocator;
|
||||||
args[1] = da_ptr;
|
args[1] = da_ptr;
|
||||||
ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
irValue *array = ir_emit_struct_ep(proc, map_ptr, 1);
|
irValue *array = ir_emit_struct_ep(proc, map_ptr, 1);
|
||||||
@@ -4465,7 +4465,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||||
args[0] = da_allocator;
|
args[0] = da_allocator;
|
||||||
args[1] = da_ptr;
|
args[1] = da_ptr;
|
||||||
ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2);
|
ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -4490,7 +4490,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
|
|
||||||
irValue **args = gb_alloc_array(a, irValue *, 1);
|
irValue **args = gb_alloc_array(a, irValue *, 1);
|
||||||
args[0] = ptr;
|
args[0] = ptr;
|
||||||
return ir_emit_global_call(proc, "free_ptr", args, 1);
|
return ir_emit_runtime_call(proc, "free_ptr", args, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4519,12 +4519,12 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
args[1] = elem_size;
|
args[1] = elem_size;
|
||||||
args[2] = elem_align;
|
args[2] = elem_align;
|
||||||
args[3] = capacity;
|
args[3] = capacity;
|
||||||
return ir_emit_global_call(proc, "__dynamic_array_reserve", args, 4);
|
return ir_emit_runtime_call(proc, "__dynamic_array_reserve", args, 4);
|
||||||
} else if (is_type_map(type)) {
|
} else if (is_type_map(type)) {
|
||||||
irValue **args = gb_alloc_array(a, irValue *, 2);
|
irValue **args = gb_alloc_array(a, irValue *, 2);
|
||||||
args[0] = ir_gen_map_header(proc, ptr, type);
|
args[0] = ir_gen_map_header(proc, ptr, type);
|
||||||
args[1] = capacity;
|
args[1] = capacity;
|
||||||
return ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2);
|
return ir_emit_runtime_call(proc, "__dynamic_map_reserve", args, 2);
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("Unknown type for 'reserve'");
|
GB_PANIC("Unknown type for 'reserve'");
|
||||||
}
|
}
|
||||||
@@ -4664,9 +4664,9 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
daa_args[4] = ir_emit_conv(proc, item_count, t_int);
|
daa_args[4] = ir_emit_conv(proc, item_count, t_int);
|
||||||
|
|
||||||
if (is_slice) {
|
if (is_slice) {
|
||||||
return ir_emit_global_call(proc, "__slice_append", daa_args, 5);
|
return ir_emit_runtime_call(proc, "__slice_append", daa_args, 5);
|
||||||
}
|
}
|
||||||
return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
|
return ir_emit_runtime_call(proc, "__dynamic_array_append", daa_args, 5);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4685,7 +4685,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
irValue **args = gb_alloc_array(a, irValue *, 2);
|
irValue **args = gb_alloc_array(a, irValue *, 2);
|
||||||
args[0] = ir_gen_map_header(proc, addr, map_type);
|
args[0] = ir_gen_map_header(proc, addr, map_type);
|
||||||
args[1] = ir_gen_map_key(proc, key, key_type);
|
args[1] = ir_gen_map_key(proc, key, key_type);
|
||||||
return ir_emit_global_call(proc, "__dynamic_map_delete", args, 2);
|
return ir_emit_runtime_call(proc, "__dynamic_map_delete", args, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4806,8 +4806,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = x;
|
args[0] = x;
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
case 64: return ir_emit_global_call(proc, "__abs_complex64", args);
|
case 64: return ir_emit_runtime_call(proc, "__abs_complex64", args);
|
||||||
case 128: return ir_emit_global_call(proc, "__abs_complex128", args);
|
case 128: return ir_emit_runtime_call(proc, "__abs_complex128", args);
|
||||||
}
|
}
|
||||||
GB_PANIC("Unknown complex type");
|
GB_PANIC("Unknown complex type");
|
||||||
} else if (is_type_float(t)) {
|
} else if (is_type_float(t)) {
|
||||||
@@ -4815,8 +4815,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = x;
|
args[0] = x;
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
case 32: return ir_emit_global_call(proc, "__abs_f32", args);
|
case 32: return ir_emit_runtime_call(proc, "__abs_f32", args);
|
||||||
case 64: return ir_emit_global_call(proc, "__abs_f64", args);
|
case 64: return ir_emit_runtime_call(proc, "__abs_f64", args);
|
||||||
}
|
}
|
||||||
GB_PANIC("Unknown float type");
|
GB_PANIC("Unknown float type");
|
||||||
}
|
}
|
||||||
@@ -5053,7 +5053,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
args[4] = ir_typeid(proc->module, src_type);
|
args[4] = ir_typeid(proc->module, src_type);
|
||||||
args[5] = ir_typeid(proc->module, dst_type);
|
args[5] = ir_typeid(proc->module, dst_type);
|
||||||
ir_emit_global_call(proc, "__type_assertion_check", args);
|
ir_emit_runtime_call(proc, "type_assertion_check", args);
|
||||||
|
|
||||||
irValue *data_ptr = v;
|
irValue *data_ptr = v;
|
||||||
return ir_emit_conv(proc, data_ptr, tv.type);
|
return ir_emit_conv(proc, data_ptr, tv.type);
|
||||||
@@ -5078,7 +5078,7 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
args[4] = any_id;
|
args[4] = any_id;
|
||||||
args[5] = id;
|
args[5] = id;
|
||||||
ir_emit_global_call(proc, "__type_assertion_check", args);
|
ir_emit_runtime_call(proc, "type_assertion_check", args);
|
||||||
|
|
||||||
return ir_emit_conv(proc, data_ptr, tv.type);
|
return ir_emit_conv(proc, data_ptr, tv.type);
|
||||||
} else {
|
} else {
|
||||||
@@ -5917,7 +5917,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
args[0] = ir_gen_map_header(proc, v, type);
|
args[0] = ir_gen_map_header(proc, v, type);
|
||||||
args[1] = ir_const_int(a, 2*cl->elems.count);
|
args[1] = ir_const_int(a, 2*cl->elems.count);
|
||||||
args[2] = ir_emit_source_code_location(proc, proc_name, pos);
|
args[2] = ir_emit_source_code_location(proc, proc_name, pos);
|
||||||
ir_emit_global_call(proc, "__dynamic_map_reserve", args);
|
ir_emit_runtime_call(proc, "__dynamic_map_reserve", args);
|
||||||
}
|
}
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
AstNode *elem = cl->elems[field_index];
|
AstNode *elem = cl->elems[field_index];
|
||||||
@@ -5945,7 +5945,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
args[2] = align;
|
args[2] = align;
|
||||||
args[3] = ir_const_int(a, 2*cl->elems.count);
|
args[3] = ir_const_int(a, 2*cl->elems.count);
|
||||||
args[4] = ir_emit_source_code_location(proc, proc_name, pos);
|
args[4] = ir_emit_source_code_location(proc, proc_name, pos);
|
||||||
ir_emit_global_call(proc, "__dynamic_array_reserve", args);
|
ir_emit_runtime_call(proc, "__dynamic_array_reserve", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 item_count = cl->elems.count;
|
i64 item_count = cl->elems.count;
|
||||||
@@ -5966,7 +5966,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
args[3] = ir_emit_conv(proc, items, t_rawptr);
|
args[3] = ir_emit_conv(proc, items, t_rawptr);
|
||||||
args[4] = ir_const_int(a, item_count);
|
args[4] = ir_const_int(a, item_count);
|
||||||
args[5] = ir_emit_source_code_location(proc, proc_name, pos);
|
args[5] = ir_emit_source_code_location(proc, proc_name, pos);
|
||||||
ir_emit_global_call(proc, "__dynamic_array_append", args);
|
ir_emit_runtime_call(proc, "__dynamic_array_append", args);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -6490,7 +6490,7 @@ void ir_build_range_string(irProcedure *proc, irValue *expr, Type *val_type,
|
|||||||
irValue *str_len = ir_emit_arith(proc, Token_Sub, count, offset, t_int);
|
irValue *str_len = ir_emit_arith(proc, Token_Sub, count, offset, t_int);
|
||||||
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
auto args = array_make<irValue *>(proc->module->allocator, 1);
|
||||||
args[0] = ir_emit_string(proc, str_elem, str_len);
|
args[0] = ir_emit_string(proc, str_elem, str_len);
|
||||||
irValue *rune_and_len = ir_emit_global_call(proc, "__string_decode_rune", args);
|
irValue *rune_and_len = ir_emit_runtime_call(proc, "__string_decode_rune", args);
|
||||||
irValue *len = ir_emit_struct_ev(proc, rune_and_len, 1);
|
irValue *len = ir_emit_struct_ev(proc, rune_and_len, 1);
|
||||||
ir_emit_store(proc, offset_, ir_emit_arith(proc, Token_Add, offset, len, t_int));
|
ir_emit_store(proc, offset_, ir_emit_arith(proc, Token_Add, offset, len, t_int));
|
||||||
|
|
||||||
@@ -7869,7 +7869,7 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
|||||||
CheckerInfo *info = m->info;
|
CheckerInfo *info = m->info;
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
irValue *global_type_table = ir_find_global_variable(proc, str_lit("__type_table"));
|
irValue *global_type_table = ir_find_global_variable(proc, str_lit("type_table"));
|
||||||
Type *type = base_type(type_deref(ir_type(ir_global_type_info_data)));
|
Type *type = base_type(type_deref(ir_type(ir_global_type_info_data)));
|
||||||
GB_ASSERT(is_type_array(type));
|
GB_ASSERT(is_type_array(type));
|
||||||
irValue *len = ir_const_int(proc->module->allocator, type->Array.count);
|
irValue *len = ir_const_int(proc->module->allocator, type->Array.count);
|
||||||
@@ -8657,7 +8657,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
irValue *argc = ir_emit_load(proc, *map_get(&proc->module->values, hash_entity(proc_params->Tuple.variables[0])));
|
irValue *argc = ir_emit_load(proc, *map_get(&proc->module->values, hash_entity(proc_params->Tuple.variables[0])));
|
||||||
irValue *argv = ir_emit_load(proc, *map_get(&proc->module->values, hash_entity(proc_params->Tuple.variables[1])));
|
irValue *argv = ir_emit_load(proc, *map_get(&proc->module->values, hash_entity(proc_params->Tuple.variables[1])));
|
||||||
|
|
||||||
irValue *global_args = ir_find_global_variable(proc, str_lit("__args__"));
|
irValue *global_args = ir_find_global_variable(proc, str_lit("args__"));
|
||||||
|
|
||||||
ir_fill_slice(proc, global_args, argv, ir_emit_conv(proc, argc, t_int));
|
ir_fill_slice(proc, global_args, argv, ir_emit_conv(proc, argc, t_int));
|
||||||
|
|
||||||
@@ -8714,7 +8714,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
e->Procedure.link_name = name;
|
e->Procedure.link_name = name;
|
||||||
|
|
||||||
ir_begin_procedure_body(proc);
|
ir_begin_procedure_body(proc);
|
||||||
ir_emit_global_call(proc, "main", nullptr, 0);
|
ir_emit_runtime_call(proc, "main", nullptr, 0);
|
||||||
ir_emit_return(proc, v_one32);
|
ir_emit_return(proc, v_one32);
|
||||||
ir_end_procedure_body(proc);
|
ir_end_procedure_body(proc);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -3680,7 +3680,8 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
elems = array_make<AstNode *>(heap_allocator());
|
elems = array_make<AstNode *>(heap_allocator());
|
||||||
while (f->curr_token.kind != Token_CloseParen &&
|
while (f->curr_token.kind != Token_CloseParen &&
|
||||||
f->curr_token.kind != Token_EOF) {
|
f->curr_token.kind != Token_EOF) {
|
||||||
AstNode *elem = parse_ident(f);
|
AstNode *elem = nullptr;
|
||||||
|
elem = parse_ident(f);
|
||||||
if (f->curr_token.kind == Token_Eq) {
|
if (f->curr_token.kind == Token_Eq) {
|
||||||
Token eq = expect_token(f, Token_Eq);
|
Token eq = expect_token(f, Token_Eq);
|
||||||
AstNode *value = parse_value(f);
|
AstNode *value = parse_value(f);
|
||||||
|
|||||||
Reference in New Issue
Block a user