mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
union type allow for any types and removes common fields
This commit is contained in:
+73
-48
@@ -34,59 +34,54 @@ CallingConvention :: enum {
|
|||||||
}
|
}
|
||||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||||
// The compiler relies upon this _exact_ order
|
// The compiler relies upon this _exact_ order
|
||||||
|
TypeInfo :: struct #ordered {
|
||||||
|
// Core Types
|
||||||
|
EnumValue :: raw_union {
|
||||||
|
f: f64;
|
||||||
|
i: i128;
|
||||||
|
}
|
||||||
|
Record :: struct #ordered {
|
||||||
|
types: []^TypeInfo;
|
||||||
|
names: []string;
|
||||||
|
offsets: []int; // offsets may not be used in tuples
|
||||||
|
usings: []bool; // usings may not be used in tuples
|
||||||
|
packed: bool;
|
||||||
|
ordered: bool;
|
||||||
|
custom_align: bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variant Types
|
||||||
TypeInfoEnumValue :: raw_union {
|
Named :: struct #ordered {name: string; base: ^TypeInfo};
|
||||||
f: f64;
|
Integer :: struct #ordered {signed: bool};
|
||||||
i: i128;
|
Rune :: struct{};
|
||||||
}
|
Float :: struct{};
|
||||||
|
Complex :: struct{};
|
||||||
TypeInfoRecord :: struct #ordered {
|
String :: struct{};
|
||||||
types: []^TypeInfo;
|
Boolean :: struct{};
|
||||||
names: []string;
|
Any :: struct{};
|
||||||
offsets: []int; // offsets may not be used in tuples
|
Pointer :: struct #ordered {
|
||||||
usings: []bool; // usings may not be used in tuples
|
|
||||||
packed: bool;
|
|
||||||
ordered: bool;
|
|
||||||
custom_align: bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TypeInfo :: union {
|
|
||||||
size: int;
|
|
||||||
align: int;
|
|
||||||
|
|
||||||
Named{name: string; base: ^TypeInfo};
|
|
||||||
Integer{signed: bool};
|
|
||||||
Rune{};
|
|
||||||
Float{};
|
|
||||||
Complex{};
|
|
||||||
String{};
|
|
||||||
Boolean{};
|
|
||||||
Any{};
|
|
||||||
Pointer{
|
|
||||||
elem: ^TypeInfo; // nil -> rawptr
|
elem: ^TypeInfo; // nil -> rawptr
|
||||||
};
|
};
|
||||||
Atomic{elem: ^TypeInfo};
|
Atomic :: struct #ordered {elem: ^TypeInfo};
|
||||||
Procedure{
|
Procedure :: struct #ordered {
|
||||||
params: ^TypeInfo; // TypeInfo.Tuple
|
params: ^TypeInfo; // TypeInfo.Tuple
|
||||||
results: ^TypeInfo; // TypeInfo.Tuple
|
results: ^TypeInfo; // TypeInfo.Tuple
|
||||||
variadic: bool;
|
variadic: bool;
|
||||||
convention: CallingConvention;
|
convention: CallingConvention;
|
||||||
};
|
};
|
||||||
Array{
|
Array :: struct #ordered {
|
||||||
elem: ^TypeInfo;
|
elem: ^TypeInfo;
|
||||||
elem_size: int;
|
elem_size: int;
|
||||||
count: int;
|
count: int;
|
||||||
};
|
};
|
||||||
DynamicArray{elem: ^TypeInfo; elem_size: int};
|
DynamicArray :: struct #ordered {elem: ^TypeInfo; elem_size: int};
|
||||||
Slice {elem: ^TypeInfo; elem_size: int};
|
Slice :: struct #ordered {elem: ^TypeInfo; elem_size: int};
|
||||||
Vector {elem: ^TypeInfo; elem_size, count: int};
|
Vector :: struct #ordered {elem: ^TypeInfo; elem_size, count: int};
|
||||||
Tuple {using record: TypeInfoRecord}; // Only really used for procedures
|
Tuple :: Record; // Only really used for procedures
|
||||||
Struct {using record: TypeInfoRecord};
|
Struct :: Record;
|
||||||
RawUnion {using record: TypeInfoRecord};
|
RawUnion :: Record;
|
||||||
Union{
|
Union :: struct #ordered {
|
||||||
common_fields: struct {
|
common_fields: struct #ordered {
|
||||||
types: []^TypeInfo;
|
types: []^TypeInfo;
|
||||||
names: []string;
|
names: []string;
|
||||||
offsets: []int; // offsets may not be used in tuples
|
offsets: []int; // offsets may not be used in tuples
|
||||||
@@ -94,22 +89,52 @@ TypeInfo :: union {
|
|||||||
variant_names: []string;
|
variant_names: []string;
|
||||||
variant_types: []^TypeInfo;
|
variant_types: []^TypeInfo;
|
||||||
};
|
};
|
||||||
Enum{
|
Enum :: struct #ordered {
|
||||||
base: ^TypeInfo;
|
base: ^TypeInfo;
|
||||||
names: []string;
|
names: []string;
|
||||||
values: []TypeInfoEnumValue;
|
values: []EnumValue;
|
||||||
};
|
};
|
||||||
Map{
|
Map :: struct #ordered {
|
||||||
key: ^TypeInfo;
|
key: ^TypeInfo;
|
||||||
value: ^TypeInfo;
|
value: ^TypeInfo;
|
||||||
generated_struct: ^TypeInfo;
|
generated_struct: ^TypeInfo;
|
||||||
count: int; // == 0 if dynamic
|
count: int; // == 0 if dynamic
|
||||||
};
|
};
|
||||||
BitField{
|
BitField :: struct #ordered {
|
||||||
names: []string;
|
names: []string;
|
||||||
bits: []i32;
|
bits: []i32;
|
||||||
offsets: []i32;
|
offsets: []i32;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Fields
|
||||||
|
size: int;
|
||||||
|
align: int;
|
||||||
|
|
||||||
|
variant: union {
|
||||||
|
Named,
|
||||||
|
Integer,
|
||||||
|
Rune,
|
||||||
|
Float,
|
||||||
|
Complex,
|
||||||
|
String,
|
||||||
|
Boolean,
|
||||||
|
Any,
|
||||||
|
Pointer,
|
||||||
|
Atomic,
|
||||||
|
Procedure,
|
||||||
|
Array,
|
||||||
|
DynamicArray,
|
||||||
|
Slice,
|
||||||
|
Vector,
|
||||||
|
Tuple,
|
||||||
|
Struct,
|
||||||
|
RawUnion,
|
||||||
|
Union,
|
||||||
|
Enum,
|
||||||
|
Map,
|
||||||
|
BitField,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): only the ones that are needed (not all types)
|
// NOTE(bill): only the ones that are needed (not all types)
|
||||||
@@ -147,7 +172,7 @@ Context :: struct #ordered {
|
|||||||
|
|
||||||
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
||||||
|
|
||||||
SourceCodeLocation :: struct {
|
SourceCodeLocation :: struct #ordered {
|
||||||
fully_pathed_filename: string;
|
fully_pathed_filename: string;
|
||||||
line, column: i64;
|
line, column: i64;
|
||||||
procedure: string;
|
procedure: string;
|
||||||
@@ -190,7 +215,7 @@ type_info_base :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
|||||||
if info == nil do return nil;
|
if info == nil do return nil;
|
||||||
|
|
||||||
base := info;
|
base := info;
|
||||||
match i in base {
|
match i in base.variant {
|
||||||
case TypeInfo.Named: base = i.base;
|
case TypeInfo.Named: base = i.base;
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
@@ -201,7 +226,7 @@ type_info_base_without_enum :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
|||||||
if info == nil do return nil;
|
if info == nil do return nil;
|
||||||
|
|
||||||
base := info;
|
base := info;
|
||||||
match i in base {
|
match i in base.variant {
|
||||||
case TypeInfo.Named: base = i.base;
|
case TypeInfo.Named: base = i.base;
|
||||||
case TypeInfo.Enum: base = i.base;
|
case TypeInfo.Enum: base = i.base;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-50
@@ -10,8 +10,8 @@ import (
|
|||||||
_BUFFER_SIZE :: 1<<12;
|
_BUFFER_SIZE :: 1<<12;
|
||||||
|
|
||||||
StringBuffer :: union {
|
StringBuffer :: union {
|
||||||
Static {buf: []u8;};
|
[]u8,
|
||||||
Dynamic{buf: [dynamic]u8;};
|
[dynamic]u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
FmtInfo :: struct {
|
FmtInfo :: struct {
|
||||||
@@ -34,28 +34,18 @@ FmtInfo :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
make_string_buffer_from_slice :: proc(b: []u8) -> StringBuffer {
|
|
||||||
return StringBuffer.Static{b};
|
|
||||||
}
|
|
||||||
|
|
||||||
make_string_dynamic_buffer :: proc() -> StringBuffer {
|
|
||||||
return StringBuffer.Dynamic{make([dynamic]u8)};
|
|
||||||
}
|
|
||||||
string_buffer_data :: proc(buf: ^StringBuffer) -> []u8 {
|
string_buffer_data :: proc(buf: ^StringBuffer) -> []u8 {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
case StringBuffer.Static:
|
case []u8: return b[..];
|
||||||
return b.buf[..];
|
case [dynamic]u8: return b[..];
|
||||||
case StringBuffer.Dynamic:
|
|
||||||
return b.buf[..];
|
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
string_buffer_data :: proc(buf: StringBuffer) -> []u8 {
|
string_buffer_data :: proc(buf: StringBuffer) -> []u8 {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
case StringBuffer.Static:
|
case []u8: return b[..];
|
||||||
return b.buf[..];
|
case [dynamic]u8: return b[..];
|
||||||
case StringBuffer.Dynamic:
|
|
||||||
return b.buf[..];
|
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@@ -69,18 +59,14 @@ write_string :: proc(buf: ^StringBuffer, s: string) {
|
|||||||
}
|
}
|
||||||
write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
case StringBuffer.Static:
|
case []u8: append(b, ...data);
|
||||||
append(&b.buf, ...data);
|
case [dynamic]u8: append(b, ...data);
|
||||||
case StringBuffer.Dynamic:
|
|
||||||
append(&b.buf, ...data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
||||||
match b in buf {
|
match b in buf {
|
||||||
case StringBuffer.Static:
|
case []u8: append(b, data);
|
||||||
append(&b.buf, data);
|
case [dynamic]u8: append(b, data);
|
||||||
case StringBuffer.Dynamic:
|
|
||||||
append(&b.buf, data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
||||||
@@ -108,7 +94,7 @@ write_int :: proc(buf: ^StringBuffer, i: i64, base: int) {
|
|||||||
|
|
||||||
fprint :: proc(fd: os.Handle, args: ...any) -> int {
|
fprint :: proc(fd: os.Handle, args: ...any) -> int {
|
||||||
data: [_BUFFER_SIZE]u8;
|
data: [_BUFFER_SIZE]u8;
|
||||||
buf := make_string_buffer_from_slice(data[..0]);
|
buf := StringBuffer(data[..0]);
|
||||||
sbprint(&buf, ...args);
|
sbprint(&buf, ...args);
|
||||||
res := string_buffer_data(buf);
|
res := string_buffer_data(buf);
|
||||||
os.write(fd, res);
|
os.write(fd, res);
|
||||||
@@ -117,7 +103,7 @@ fprint :: proc(fd: os.Handle, args: ...any) -> int {
|
|||||||
|
|
||||||
fprintln :: proc(fd: os.Handle, args: ...any) -> int {
|
fprintln :: proc(fd: os.Handle, args: ...any) -> int {
|
||||||
data: [_BUFFER_SIZE]u8;
|
data: [_BUFFER_SIZE]u8;
|
||||||
buf := make_string_buffer_from_slice(data[..0]);
|
buf := StringBuffer(data[..0]);
|
||||||
sbprintln(&buf, ...args);
|
sbprintln(&buf, ...args);
|
||||||
res := string_buffer_data(buf);
|
res := string_buffer_data(buf);
|
||||||
os.write(fd, res);
|
os.write(fd, res);
|
||||||
@@ -125,7 +111,7 @@ fprintln :: proc(fd: os.Handle, args: ...any) -> int {
|
|||||||
}
|
}
|
||||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
|
fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
|
||||||
data: [_BUFFER_SIZE]u8;
|
data: [_BUFFER_SIZE]u8;
|
||||||
buf := make_string_buffer_from_slice(data[..0]);
|
buf := StringBuffer(data[..0]);
|
||||||
sbprintf(&buf, fmt, ...args);
|
sbprintf(&buf, fmt, ...args);
|
||||||
res := string_buffer_data(buf);
|
res := string_buffer_data(buf);
|
||||||
os.write(fd, res);
|
os.write(fd, res);
|
||||||
@@ -145,17 +131,17 @@ printf_err :: proc(fmt: string, args: ...any) -> int { return fprintf(os.stderr
|
|||||||
// aprint* procedures return a string that was allocated with the current context
|
// aprint* procedures return a string that was allocated with the current context
|
||||||
// They must be freed accordingly
|
// They must be freed accordingly
|
||||||
aprint :: proc(args: ...any) -> string {
|
aprint :: proc(args: ...any) -> string {
|
||||||
buf := make_string_dynamic_buffer();
|
buf := StringBuffer(make([dynamic]u8));
|
||||||
sbprint(&buf, ...args);
|
sbprint(&buf, ...args);
|
||||||
return to_string(buf);
|
return to_string(buf);
|
||||||
}
|
}
|
||||||
aprintln :: proc(args: ...any) -> string {
|
aprintln :: proc(args: ...any) -> string {
|
||||||
buf := make_string_dynamic_buffer();
|
buf := StringBuffer(make([dynamic]u8));
|
||||||
sbprintln(&buf, ...args);
|
sbprintln(&buf, ...args);
|
||||||
return to_string(buf);
|
return to_string(buf);
|
||||||
}
|
}
|
||||||
aprintf :: proc(fmt: string, args: ...any) -> string {
|
aprintf :: proc(fmt: string, args: ...any) -> string {
|
||||||
buf := make_string_dynamic_buffer();
|
buf := StringBuffer(make([dynamic]u8));
|
||||||
sbprintf(&buf, fmt, ...args);
|
sbprintf(&buf, fmt, ...args);
|
||||||
return to_string(buf);
|
return to_string(buf);
|
||||||
}
|
}
|
||||||
@@ -164,15 +150,15 @@ aprintf :: proc(fmt: string, args: ...any) -> string {
|
|||||||
// bprint* procedures return a string that was allocated with the current context
|
// bprint* procedures return a string that was allocated with the current context
|
||||||
// They must be freed accordingly
|
// They must be freed accordingly
|
||||||
bprint :: proc(buf: []u8, args: ...any) -> string {
|
bprint :: proc(buf: []u8, args: ...any) -> string {
|
||||||
sb := make_string_buffer_from_slice(buf[..0..len(buf)]);
|
sb := StringBuffer(buf[..0..len(buf)]);
|
||||||
return sbprint(&sb, ...args);
|
return sbprint(&sb, ...args);
|
||||||
}
|
}
|
||||||
bprintln :: proc(buf: []u8, args: ...any) -> string {
|
bprintln :: proc(buf: []u8, args: ...any) -> string {
|
||||||
sb := make_string_buffer_from_slice(buf[..0..len(buf)]);
|
sb := StringBuffer(buf[..0..len(buf)]);
|
||||||
return sbprintln(&sb, ...args);
|
return sbprintln(&sb, ...args);
|
||||||
}
|
}
|
||||||
bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
|
bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
|
||||||
sb := make_string_buffer_from_slice(buf[..0..len(buf)]);
|
sb := StringBuffer(buf[..0..len(buf)]);
|
||||||
return sbprintf(&sb, fmt, ...args);
|
return sbprintf(&sb, fmt, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +169,7 @@ bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
|
|||||||
|
|
||||||
fprint_type :: proc(fd: os.Handle, info: ^TypeInfo) {
|
fprint_type :: proc(fd: os.Handle, info: ^TypeInfo) {
|
||||||
data: [_BUFFER_SIZE]u8;
|
data: [_BUFFER_SIZE]u8;
|
||||||
buf := make_string_buffer_from_slice(data[..0]);
|
buf := StringBuffer(data[..0]);
|
||||||
write_type(&buf, info);
|
write_type(&buf, info);
|
||||||
os.write(fd, string_buffer_data(buf));
|
os.write(fd, string_buffer_data(buf));
|
||||||
}
|
}
|
||||||
@@ -192,7 +178,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
if ti == nil do return;
|
if ti == nil do return;
|
||||||
|
|
||||||
using TypeInfo;
|
using TypeInfo;
|
||||||
match info in ti {
|
match info in ti.variant {
|
||||||
case Named:
|
case Named:
|
||||||
write_string(buf, info.name);
|
write_string(buf, info.name);
|
||||||
case Integer:
|
case Integer:
|
||||||
@@ -201,18 +187,18 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
case ti == type_info(uint): write_string(buf, "uint");
|
case ti == type_info(uint): write_string(buf, "uint");
|
||||||
case:
|
case:
|
||||||
write_string(buf, info.signed ? "i" : "u");
|
write_string(buf, info.signed ? "i" : "u");
|
||||||
write_int(buf, i64(8*info.size), 10);
|
write_int(buf, i64(8*ti.size), 10);
|
||||||
}
|
}
|
||||||
case Rune:
|
case Rune:
|
||||||
write_string(buf, "rune");
|
write_string(buf, "rune");
|
||||||
case Float:
|
case Float:
|
||||||
match info.size {
|
match ti.size {
|
||||||
case 2: write_string(buf, "f16");
|
case 2: write_string(buf, "f16");
|
||||||
case 4: write_string(buf, "f32");
|
case 4: write_string(buf, "f32");
|
||||||
case 8: write_string(buf, "f64");
|
case 8: write_string(buf, "f64");
|
||||||
}
|
}
|
||||||
case Complex:
|
case Complex:
|
||||||
match info.size {
|
match ti.size {
|
||||||
case 4: write_string(buf, "complex32");
|
case 4: write_string(buf, "complex32");
|
||||||
case 8: write_string(buf, "complex64");
|
case 8: write_string(buf, "complex64");
|
||||||
case 16: write_string(buf, "complex128");
|
case 16: write_string(buf, "complex128");
|
||||||
@@ -237,7 +223,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
if info.params == nil {
|
if info.params == nil {
|
||||||
write_string(buf, "()");
|
write_string(buf, "()");
|
||||||
} else {
|
} else {
|
||||||
t := info.params.(^Tuple);
|
t := info.params.variant.(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, ", ");
|
||||||
@@ -295,7 +281,7 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
if info.ordered do write_string(buf, "#ordered ");
|
if info.ordered do write_string(buf, "#ordered ");
|
||||||
if info.custom_align {
|
if info.custom_align {
|
||||||
write_string(buf, "#align ");
|
write_string(buf, "#align ");
|
||||||
write_int(buf, i64(info.align), 10);
|
write_int(buf, i64(ti.align), 10);
|
||||||
write_byte(buf, ' ');
|
write_byte(buf, ' ');
|
||||||
}
|
}
|
||||||
write_byte(buf, '{');
|
write_byte(buf, '{');
|
||||||
@@ -324,8 +310,8 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
write_byte(buf, '{');
|
write_byte(buf, '{');
|
||||||
defer write_byte(buf, '}');
|
defer write_byte(buf, '}');
|
||||||
|
|
||||||
variant_type := type_info_base(info.variant_types[i]);
|
variant_type := type_info_base(info.variant_types[i]).variant;
|
||||||
variant := variant_type.(^Struct);
|
variant := (&variant_type).(Struct);
|
||||||
|
|
||||||
vc := len(variant.names)-len(cf.names);
|
vc := len(variant.names)-len(cf.names);
|
||||||
for j in 0..vc {
|
for j in 0..vc {
|
||||||
@@ -359,9 +345,9 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
write_string(buf, "}");
|
write_string(buf, "}");
|
||||||
case BitField:
|
case BitField:
|
||||||
write_string(buf, "bit_field ");
|
write_string(buf, "bit_field ");
|
||||||
if info.align != 1 {
|
if ti.align != 1 {
|
||||||
write_string(buf, "#align ");
|
write_string(buf, "#align ");
|
||||||
write_int(buf, i64(info.align), 10);
|
write_int(buf, i64(ti.align), 10);
|
||||||
write_rune(buf, ' ');
|
write_rune(buf, ' ');
|
||||||
}
|
}
|
||||||
write_string(buf, " {");
|
write_string(buf, " {");
|
||||||
@@ -697,7 +683,7 @@ fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using TypeInfo;
|
using TypeInfo;
|
||||||
match e in v.type_info {
|
match e in v.type_info.variant {
|
||||||
case:
|
case:
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
@@ -768,9 +754,9 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using TypeInfo;
|
using TypeInfo;
|
||||||
match info in v.type_info {
|
match info in v.type_info.variant {
|
||||||
case Named:
|
case Named:
|
||||||
match b in info.base {
|
match b in info.base.variant {
|
||||||
case Struct:
|
case Struct:
|
||||||
if verb != 'v' {
|
if verb != 'v' {
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
@@ -866,9 +852,9 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
|
|
||||||
entries := &(^raw.DynamicMap(v.data).entries);
|
entries := &(^raw.DynamicMap(v.data).entries);
|
||||||
gs := type_info_base(info.generated_struct).(^Struct);
|
gs := type_info_base(info.generated_struct).variant.(Struct);
|
||||||
ed := type_info_base(gs.types[1]).(^DynamicArray);
|
ed := type_info_base(gs.types[1]).variant.(DynamicArray);
|
||||||
entry_type := ed.elem.(^Struct);
|
entry_type := ed.elem.variant.(Struct);
|
||||||
entry_size := ed.elem_size;
|
entry_size := ed.elem_size;
|
||||||
|
|
||||||
for i in 0..entries.len {
|
for i in 0..entries.len {
|
||||||
|
|||||||
+15
-15
@@ -208,15 +208,15 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
|||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||||
using TypeInfo;
|
using TypeInfo;
|
||||||
match info in type_info {
|
match info in type_info.variant {
|
||||||
case Named:
|
case Named:
|
||||||
return align_of_type_info(info.base);
|
return align_of_type_info(info.base);
|
||||||
case Integer:
|
case Integer:
|
||||||
return info.size;
|
return type_info.align;
|
||||||
case Rune:
|
case Rune:
|
||||||
return info.size;
|
return type_info.align;
|
||||||
case Float:
|
case Float:
|
||||||
return info.size;
|
return type_info.align;
|
||||||
case String:
|
case String:
|
||||||
return WORD_SIZE;
|
return WORD_SIZE;
|
||||||
case Boolean:
|
case Boolean:
|
||||||
@@ -239,13 +239,13 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
|||||||
total := size * count;
|
total := size * count;
|
||||||
return clamp(total, 1, MAX_ALIGN);
|
return clamp(total, 1, MAX_ALIGN);
|
||||||
case Tuple:
|
case Tuple:
|
||||||
return info.align;
|
return type_info.align;
|
||||||
case Struct:
|
case Struct:
|
||||||
return info.align;
|
return type_info.align;
|
||||||
case Union:
|
case Union:
|
||||||
return info.align;
|
return type_info.align;
|
||||||
case RawUnion:
|
case RawUnion:
|
||||||
return info.align;
|
return type_info.align;
|
||||||
case Enum:
|
case Enum:
|
||||||
return align_of_type_info(info.base);
|
return align_of_type_info(info.base);
|
||||||
case Map:
|
case Map:
|
||||||
@@ -263,15 +263,15 @@ align_formula :: proc(size, align: int) -> int {
|
|||||||
size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
using TypeInfo;
|
using TypeInfo;
|
||||||
match info in type_info {
|
match info in type_info.variant {
|
||||||
case Named:
|
case Named:
|
||||||
return size_of_type_info(info.base);
|
return size_of_type_info(info.base);
|
||||||
case Integer:
|
case Integer:
|
||||||
return info.size;
|
return type_info.size;
|
||||||
case Rune:
|
case Rune:
|
||||||
return info.size;
|
return type_info.size;
|
||||||
case Float:
|
case Float:
|
||||||
return info.size;
|
return type_info.size;
|
||||||
case String:
|
case String:
|
||||||
return 2*WORD_SIZE;
|
return 2*WORD_SIZE;
|
||||||
case Boolean:
|
case Boolean:
|
||||||
@@ -301,11 +301,11 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
|||||||
alignment := align_formula(size, align);
|
alignment := align_formula(size, align);
|
||||||
return alignment*(count-1) + size;
|
return alignment*(count-1) + size;
|
||||||
case Struct:
|
case Struct:
|
||||||
return info.size;
|
return type_info.size;
|
||||||
case Union:
|
case Union:
|
||||||
return info.size;
|
return type_info.size;
|
||||||
case RawUnion:
|
case RawUnion:
|
||||||
return info.size;
|
return type_info.size;
|
||||||
case Enum:
|
case Enum:
|
||||||
return size_of_type_info(info.base);
|
return size_of_type_info(info.base);
|
||||||
case Map:
|
case Map:
|
||||||
|
|||||||
+20
-20
@@ -1,6 +1,6 @@
|
|||||||
is_signed :: proc(info: ^TypeInfo) -> bool {
|
is_signed :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
match i in type_info_base(info) {
|
match i in type_info_base(info).variant {
|
||||||
case TypeInfo.Integer: return i.signed;
|
case TypeInfo.Integer: return i.signed;
|
||||||
case TypeInfo.Float: return true;
|
case TypeInfo.Float: return true;
|
||||||
}
|
}
|
||||||
@@ -8,96 +8,96 @@ is_signed :: proc(info: ^TypeInfo) -> bool {
|
|||||||
}
|
}
|
||||||
is_integer :: proc(info: ^TypeInfo) -> bool {
|
is_integer :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Integer);
|
_, ok := type_info_base(info).variant.(TypeInfo.Integer);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_rune :: proc(info: ^TypeInfo) -> bool {
|
is_rune :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Rune);
|
_, ok := type_info_base(info).variant.(TypeInfo.Rune);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_float :: proc(info: ^TypeInfo) -> bool {
|
is_float :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Float);
|
_, ok := type_info_base(info).variant.(TypeInfo.Float);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_complex :: proc(info: ^TypeInfo) -> bool {
|
is_complex :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Complex);
|
_, ok := type_info_base(info).variant.(TypeInfo.Complex);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_any :: proc(info: ^TypeInfo) -> bool {
|
is_any :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Any);
|
_, ok := type_info_base(info).variant.(TypeInfo.Any);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_string :: proc(info: ^TypeInfo) -> bool {
|
is_string :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.String);
|
_, ok := type_info_base(info).variant.(TypeInfo.String);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_boolean :: proc(info: ^TypeInfo) -> bool {
|
is_boolean :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Boolean);
|
_, ok := type_info_base(info).variant.(TypeInfo.Boolean);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_pointer :: proc(info: ^TypeInfo) -> bool {
|
is_pointer :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Pointer);
|
_, ok := type_info_base(info).variant.(TypeInfo.Pointer);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_procedure :: proc(info: ^TypeInfo) -> bool {
|
is_procedure :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Procedure);
|
_, ok := type_info_base(info).variant.(TypeInfo.Procedure);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_array :: proc(info: ^TypeInfo) -> bool {
|
is_array :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Array);
|
_, ok := type_info_base(info).variant.(TypeInfo.Array);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_dynamic_array :: proc(info: ^TypeInfo) -> bool {
|
is_dynamic_array :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.DynamicArray);
|
_, ok := type_info_base(info).variant.(TypeInfo.DynamicArray);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_dynamic_map :: proc(info: ^TypeInfo) -> bool {
|
is_dynamic_map :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Map);
|
_, ok := type_info_base(info).variant.(TypeInfo.Map);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_slice :: proc(info: ^TypeInfo) -> bool {
|
is_slice :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Slice);
|
_, ok := type_info_base(info).variant.(TypeInfo.Slice);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_vector :: proc(info: ^TypeInfo) -> bool {
|
is_vector :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Vector);
|
_, ok := type_info_base(info).variant.(TypeInfo.Vector);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_tuple :: proc(info: ^TypeInfo) -> bool {
|
is_tuple :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Tuple);
|
_, ok := type_info_base(info).variant.(TypeInfo.Tuple);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_struct :: proc(info: ^TypeInfo) -> bool {
|
is_struct :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Struct);
|
_, ok := type_info_base(info).variant.(TypeInfo.Struct);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_union :: proc(info: ^TypeInfo) -> bool {
|
is_union :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Union);
|
_, ok := type_info_base(info).variant.(TypeInfo.Union);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_raw_union :: proc(info: ^TypeInfo) -> bool {
|
is_raw_union :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.RawUnion);
|
_, ok := type_info_base(info).variant.(TypeInfo.RawUnion);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
is_enum :: proc(info: ^TypeInfo) -> bool {
|
is_enum :: proc(info: ^TypeInfo) -> bool {
|
||||||
if info == nil do return false;
|
if info == nil do return false;
|
||||||
_, ok := type_info_base(info).(^TypeInfo.Enum);
|
_, ok := type_info_base(info).variant.(TypeInfo.Enum);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-110
@@ -500,8 +500,8 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
|
|
||||||
if (is_type_union(dst)) {
|
if (is_type_union(dst)) {
|
||||||
for (isize i = 0; i < dst->Record.variant_count; i++) {
|
for (isize i = 0; i < dst->Record.variant_count; i++) {
|
||||||
Entity *f = dst->Record.variants[i];
|
Type *vt = dst->Record.variants[i];
|
||||||
if (are_types_identical(f->type, s)) {
|
if (are_types_identical(vt, s)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -980,41 +980,17 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
|||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
|
|
||||||
isize variant_count = ut->variants.count+1;
|
isize variant_count = ut->variants.count+1;
|
||||||
isize min_field_count = 0;
|
|
||||||
for_array(i, ut->fields) {
|
|
||||||
AstNode *field = ut->fields[i];
|
|
||||||
switch (field->kind) {
|
|
||||||
case_ast_node(f, ValueDecl, field);
|
|
||||||
min_field_count += f->names.count;
|
|
||||||
case_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
defer (gb_temp_arena_memory_end(tmp));
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
Map<Entity *> entity_map = {}; // Key: String
|
|
||||||
map_init_with_reserve(&entity_map, c->tmp_allocator, 2*variant_count);
|
|
||||||
|
|
||||||
Entity *using_index_expr = nullptr;
|
Entity *using_index_expr = nullptr;
|
||||||
|
|
||||||
Array<Entity *> variants = {};
|
Array<Type *> variants = {};
|
||||||
array_init(&variants, heap_allocator(), variant_count);
|
array_init(&variants, c->allocator, variant_count);
|
||||||
|
array_add(&variants, t_invalid);
|
||||||
array_add(&variants, make_entity_type_name(c->allocator, c->context.scope, empty_token, nullptr));
|
|
||||||
|
|
||||||
auto fields = check_fields(c, nullptr, ut->fields, min_field_count, str_lit("union"));
|
|
||||||
|
|
||||||
for (isize i = 0; i < fields.count; i++) {
|
|
||||||
Entity *f = fields[i];
|
|
||||||
String name = f->token.string;
|
|
||||||
map_set(&entity_map, hash_string(name), f);
|
|
||||||
}
|
|
||||||
|
|
||||||
union_type->Record.scope = c->context.scope;
|
union_type->Record.scope = c->context.scope;
|
||||||
union_type->Record.fields = fields.data;
|
|
||||||
union_type->Record.fields_in_src_order = fields.data;
|
|
||||||
union_type->Record.field_count = fields.count;
|
|
||||||
union_type->Record.are_offsets_set = false;
|
union_type->Record.are_offsets_set = false;
|
||||||
union_type->Record.is_ordered = true;
|
union_type->Record.is_ordered = true;
|
||||||
{
|
{
|
||||||
@@ -1023,75 +999,21 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, ut->variants) {
|
for_array(i, ut->variants) {
|
||||||
AstNode *variant = ut->variants[i];
|
AstNode *node = ut->variants[i];
|
||||||
if (variant->kind != AstNode_UnionField) {
|
Type *t = check_type(c, node);
|
||||||
continue;
|
if (t != nullptr && t != t_invalid) {
|
||||||
}
|
bool ok = true;
|
||||||
ast_node(f, UnionField, variant);
|
for_array(j, variants) {
|
||||||
Token name_token = f->name->Ident.token;
|
if (are_types_identical(t, variants[j])) {
|
||||||
|
ok = false;
|
||||||
Type *base_type = make_type_struct(c->allocator);
|
gbString str = type_to_string(t);
|
||||||
{
|
error(node, "Duplicate variant type `%s`", str);
|
||||||
ast_node(fl, FieldList, f->list);
|
gb_string_free(str);
|
||||||
|
break;
|
||||||
// NOTE(bill): Copy the contents for the common fields for now
|
|
||||||
Array<AstNode *> list = {};
|
|
||||||
array_init_count(&list, c->allocator, ut->fields.count+fl->list.count);
|
|
||||||
gb_memmove_array(list.data, ut->fields.data, ut->fields.count);
|
|
||||||
gb_memmove_array(list.data+ut->fields.count, fl->list.data, fl->list.count);
|
|
||||||
|
|
||||||
isize list_count = 0;
|
|
||||||
for_array(j, list) {
|
|
||||||
if (list[j]->kind == AstNode_Field) {
|
|
||||||
list_count += list[j]->Field.names.count;
|
|
||||||
} else {
|
|
||||||
ast_node(f, ValueDecl, list[j]);
|
|
||||||
list_count += f->names.count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ok) array_add(&variants, t);
|
||||||
|
|
||||||
Token token = name_token;
|
|
||||||
token.kind = Token_struct;
|
|
||||||
AstNode *dummy_struct = ast_struct_type(c->curr_ast_file, token, list, list_count, false, true, nullptr);
|
|
||||||
|
|
||||||
check_open_scope(c, dummy_struct);
|
|
||||||
base_type->Record.names = make_names_field_for_record(c, c->context.scope);
|
|
||||||
auto fields = check_fields(c, dummy_struct, list, list_count, str_lit("variant"));
|
|
||||||
base_type->Record.is_packed = false;
|
|
||||||
base_type->Record.is_ordered = true;
|
|
||||||
base_type->Record.fields = fields.data;
|
|
||||||
base_type->Record.fields_in_src_order = fields.data;
|
|
||||||
base_type->Record.field_count = fields.count;
|
|
||||||
base_type->Record.node = dummy_struct;
|
|
||||||
base_type->Record.variant_parent = named_type != nullptr ? named_type : union_type;
|
|
||||||
base_type->Record.variant_index = variants.count;
|
|
||||||
|
|
||||||
|
|
||||||
type_set_offsets(c->allocator, base_type);
|
|
||||||
|
|
||||||
check_close_scope(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *type = make_type_named(c->allocator, name_token.string, base_type, nullptr);
|
|
||||||
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, type);
|
|
||||||
type->Named.type_name = e;
|
|
||||||
add_entity(c, c->context.scope, f->name, e);
|
|
||||||
|
|
||||||
if (name_token.string == "_") {
|
|
||||||
error(name_token, "`_` cannot be used a union subtype");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashKey key = hash_string(name_token.string);
|
|
||||||
if (map_get(&entity_map, key) != nullptr) {
|
|
||||||
// NOTE(bill): Scope checking already checks the declaration
|
|
||||||
error(name_token, "`%.*s` is already declared in this union", LIT(name_token.string));
|
|
||||||
} else {
|
|
||||||
map_set(&entity_map, key, e);
|
|
||||||
array_add(&variants, e);
|
|
||||||
}
|
|
||||||
add_entity_use(c, f->name, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type_set_offsets(c->allocator, union_type);
|
type_set_offsets(c->allocator, union_type);
|
||||||
@@ -6889,28 +6811,17 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
|
|
||||||
|
|
||||||
bool src_is_ptr = is_type_pointer(o->type);
|
bool src_is_ptr = is_type_pointer(o->type);
|
||||||
bool dst_is_ptr = is_type_pointer(t);
|
|
||||||
Type *src = type_deref(o->type);
|
Type *src = type_deref(o->type);
|
||||||
Type *dst = type_deref(t);
|
Type *dst = t;
|
||||||
Type *bsrc = base_type(src);
|
Type *bsrc = base_type(src);
|
||||||
Type *bdst = base_type(dst);
|
Type *bdst = base_type(dst);
|
||||||
|
|
||||||
if (src_is_ptr != dst_is_ptr) {
|
|
||||||
gbString src_type_str = type_to_string(o->type);
|
|
||||||
gbString dst_type_str = type_to_string(t);
|
|
||||||
error(o->expr, "Invalid type assertion types: `%s` and `%s`", src_type_str, dst_type_str);
|
|
||||||
gb_string_free(dst_type_str);
|
|
||||||
gb_string_free(src_type_str);
|
|
||||||
o->mode = Addressing_Invalid;
|
|
||||||
o->expr = node;
|
|
||||||
return kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_type_union(src)) {
|
if (is_type_union(src)) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
for (isize i = 1; i < bsrc->Record.variant_count; i++) {
|
for (isize i = 1; i < bsrc->Record.variant_count; i++) {
|
||||||
Entity *f = bsrc->Record.variants[i];
|
Type *vt = bsrc->Record.variants[i];
|
||||||
if (are_types_identical(f->type, dst)) {
|
if (are_types_identical(vt, dst)) {
|
||||||
ok = true;
|
ok = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -7088,6 +6999,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
|
|
||||||
case Type_Slice:
|
case Type_Slice:
|
||||||
valid = true;
|
valid = true;
|
||||||
|
o->type = type_deref(o->type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_DynamicArray:
|
case Type_DynamicArray:
|
||||||
@@ -7602,7 +7514,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
case_ast_node(st, UnionType, node);
|
case_ast_node(st, UnionType, node);
|
||||||
str = gb_string_appendc(str, "union ");
|
str = gb_string_appendc(str, "union ");
|
||||||
str = gb_string_appendc(str, "{");
|
str = gb_string_appendc(str, "{");
|
||||||
str = write_record_fields_to_string(str, st->fields);
|
str = write_record_fields_to_string(str, st->variants);
|
||||||
str = gb_string_appendc(str, "}");
|
str = gb_string_appendc(str, "}");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1504,8 +1504,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
GB_ASSERT(is_type_union(bt));
|
GB_ASSERT(is_type_union(bt));
|
||||||
bool tag_type_found = false;
|
bool tag_type_found = false;
|
||||||
for (isize i = 0; i < bt->Record.variant_count; i++) {
|
for (isize i = 0; i < bt->Record.variant_count; i++) {
|
||||||
Entity *f = bt->Record.variants[i];
|
Type *vt = bt->Record.variants[i];
|
||||||
if (are_types_identical(f->type, y.type)) {
|
if (are_types_identical(vt, y.type)) {
|
||||||
tag_type_found = true;
|
tag_type_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-44
@@ -1156,8 +1156,7 @@ void add_type_info_type(Checker *c, Type *t) {
|
|||||||
case TypeRecord_Union:
|
case TypeRecord_Union:
|
||||||
add_type_info_type(c, t_int);
|
add_type_info_type(c, t_int);
|
||||||
for (isize i = 0; i < bt->Record.variant_count; i++) {
|
for (isize i = 0; i < bt->Record.variant_count; i++) {
|
||||||
Entity *f = bt->Record.variants[i];
|
add_type_info_type(c, bt->Record.variants[i]);
|
||||||
add_type_info_type(c, f->type);
|
|
||||||
}
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
default:
|
default:
|
||||||
@@ -1307,30 +1306,30 @@ Entity *find_core_entity(Checker *c, String name) {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity *find_sub_core_entity(TypeRecord *parent, String name) {
|
||||||
|
GB_ASSERT(parent->scope->parent->is_global);
|
||||||
|
Entity *e = current_scope_lookup_entity(parent->scope, name);
|
||||||
|
if (e == nullptr) {
|
||||||
|
compiler_error("Could not find type declaration for `%.*s`\n"
|
||||||
|
"Is `_preload.odin` missing from the `core` directory relative to odin.exe?", LIT(name));
|
||||||
|
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type);
|
||||||
|
|
||||||
void init_preload(Checker *c) {
|
void init_preload(Checker *c) {
|
||||||
if (t_type_info == nullptr) {
|
if (t_type_info == nullptr) {
|
||||||
Entity *type_info_entity = find_core_entity(c, str_lit("TypeInfo"));
|
Entity *type_info_entity = find_core_entity(c, str_lit("TypeInfo"));
|
||||||
|
|
||||||
t_type_info = type_info_entity->type;
|
t_type_info = type_info_entity->type;
|
||||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||||
GB_ASSERT(is_type_union(type_info_entity->type));
|
GB_ASSERT(is_type_struct(type_info_entity->type));
|
||||||
TypeRecord *record = &base_type(type_info_entity->type)->Record;
|
TypeRecord *record = &base_type(type_info_entity->type)->Record;
|
||||||
|
|
||||||
// Entity *type_info_record = current_scope_lookup_entity(record->scope, str_lit("Record"));
|
Entity *type_info_record = find_sub_core_entity(record, str_lit("Record"));
|
||||||
// if (type_info_record == nullptr) {
|
Entity *type_info_enum_value = find_sub_core_entity(record, str_lit("EnumValue"));
|
||||||
// compiler_error("Could not find type declaration for TypeInfo.Record\n"
|
|
||||||
// "Is `_preload.odin` missing from the `core` directory relative to the odin executable?");
|
|
||||||
// }
|
|
||||||
// Entity *type_info_enum_value = current_scope_lookup_entity(record->scope, str_lit("EnumValue"));
|
|
||||||
// if (type_info_record == nullptr) {
|
|
||||||
// compiler_error("Could not find type declaration for TypeInfo.EnumValue\n"
|
|
||||||
// "Is `_preload.odin` missing from the `core` directory relative to the odin executable?");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// GB_ASSERT(type_info_record->type != nullptr);
|
|
||||||
// GB_ASSERT(type_info_enum_value->type != nullptr);
|
|
||||||
Entity *type_info_record = find_core_entity(c, str_lit("TypeInfoRecord"));
|
|
||||||
Entity *type_info_enum_value = find_core_entity(c, str_lit("TypeInfoEnumValue"));
|
|
||||||
|
|
||||||
|
|
||||||
t_type_info_record = type_info_record->type;
|
t_type_info_record = type_info_record->type;
|
||||||
@@ -1338,33 +1337,38 @@ void init_preload(Checker *c) {
|
|||||||
t_type_info_enum_value = type_info_enum_value->type;
|
t_type_info_enum_value = type_info_enum_value->type;
|
||||||
t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value);
|
t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value);
|
||||||
|
|
||||||
|
GB_ASSERT(record->field_count == 3);
|
||||||
|
|
||||||
|
Entity *type_info_variant = record->fields_in_src_order[2];
|
||||||
|
Type *tiv_type = type_info_variant->type;
|
||||||
|
GB_ASSERT(is_type_union(tiv_type));
|
||||||
|
TypeRecord *tiv = &tiv_type->Record;
|
||||||
|
|
||||||
if (record->variant_count != 23) {
|
if (tiv->variant_count != 23) {
|
||||||
compiler_error("Invalid `TypeInfo` layout");
|
compiler_error("Invalid `TypeInfo` layout");
|
||||||
}
|
}
|
||||||
t_type_info_named = record->variants[ 1]->type;
|
t_type_info_named = tiv->variants[ 1];
|
||||||
t_type_info_integer = record->variants[ 2]->type;
|
t_type_info_integer = tiv->variants[ 2];
|
||||||
t_type_info_rune = record->variants[ 3]->type;
|
t_type_info_rune = tiv->variants[ 3];
|
||||||
t_type_info_float = record->variants[ 4]->type;
|
t_type_info_float = tiv->variants[ 4];
|
||||||
t_type_info_complex = record->variants[ 5]->type;
|
t_type_info_complex = tiv->variants[ 5];
|
||||||
t_type_info_string = record->variants[ 6]->type;
|
t_type_info_string = tiv->variants[ 6];
|
||||||
t_type_info_boolean = record->variants[ 7]->type;
|
t_type_info_boolean = tiv->variants[ 7];
|
||||||
t_type_info_any = record->variants[ 8]->type;
|
t_type_info_any = tiv->variants[ 8];
|
||||||
t_type_info_pointer = record->variants[ 9]->type;
|
t_type_info_pointer = tiv->variants[ 9];
|
||||||
t_type_info_atomic = record->variants[10]->type;
|
t_type_info_atomic = tiv->variants[10];
|
||||||
t_type_info_procedure = record->variants[11]->type;
|
t_type_info_procedure = tiv->variants[11];
|
||||||
t_type_info_array = record->variants[12]->type;
|
t_type_info_array = tiv->variants[12];
|
||||||
t_type_info_dynamic_array = record->variants[13]->type;
|
t_type_info_dynamic_array = tiv->variants[13];
|
||||||
t_type_info_slice = record->variants[14]->type;
|
t_type_info_slice = tiv->variants[14];
|
||||||
t_type_info_vector = record->variants[15]->type;
|
t_type_info_vector = tiv->variants[15];
|
||||||
t_type_info_tuple = record->variants[16]->type;
|
t_type_info_tuple = tiv->variants[16];
|
||||||
t_type_info_struct = record->variants[17]->type;
|
t_type_info_struct = tiv->variants[17];
|
||||||
t_type_info_raw_union = record->variants[18]->type;
|
t_type_info_raw_union = tiv->variants[18];
|
||||||
t_type_info_union = record->variants[19]->type;
|
t_type_info_union = tiv->variants[19];
|
||||||
t_type_info_enum = record->variants[20]->type;
|
t_type_info_enum = tiv->variants[20];
|
||||||
t_type_info_map = record->variants[21]->type;
|
t_type_info_map = tiv->variants[21];
|
||||||
t_type_info_bit_field = record->variants[22]->type;
|
t_type_info_bit_field = tiv->variants[22];
|
||||||
|
|
||||||
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named);
|
||||||
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer);
|
||||||
@@ -1719,9 +1723,6 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token token = name->Ident.token;
|
Token token = name->Ident.token;
|
||||||
if (token.string == "EnumValue") {
|
|
||||||
gb_printf_err("EnumValue %p\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *fl = c->context.curr_foreign_library;
|
AstNode *fl = c->context.curr_foreign_library;
|
||||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, c->context.decl);
|
||||||
|
|||||||
+128
-95
@@ -2355,7 +2355,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
|
|
||||||
if (is_type_struct(t)) {
|
if (is_type_struct(t)) {
|
||||||
GB_ASSERT(t->Record.field_count > 0);
|
GB_ASSERT(t->Record.field_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
GB_ASSERT_MSG(gb_is_between(index, 0, t->Record.field_count-1), "0..%d..%d", index, t->Record.field_count);
|
||||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
type_set_offsets(a, t);
|
type_set_offsets(a, t);
|
||||||
@@ -2950,12 +2950,12 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
|
|
||||||
if (is_type_union(dst)) {
|
if (is_type_union(dst)) {
|
||||||
for (isize i = 1; i < dst->Record.variant_count; i++) {
|
for (isize i = 1; i < dst->Record.variant_count; i++) {
|
||||||
Entity *f = dst->Record.variants[i];
|
Type *vt = dst->Record.variants[i];
|
||||||
if (are_types_identical(f->type, src_type)) {
|
if (are_types_identical(vt, src_type)) {
|
||||||
ir_emit_comment(proc, str_lit("union - child to parent"));
|
ir_emit_comment(proc, str_lit("union - child to parent"));
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
irValue *parent = ir_add_local_generated(proc, t);
|
irValue *parent = ir_add_local_generated(proc, t);
|
||||||
irValue *underlying = ir_emit_conv(proc, parent, make_type_pointer(a, f->type));
|
irValue *underlying = ir_emit_conv(proc, parent, make_type_pointer(a, vt));
|
||||||
ir_emit_store(proc, underlying, value);
|
ir_emit_store(proc, underlying, value);
|
||||||
|
|
||||||
irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
|
irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
|
||||||
@@ -3207,6 +3207,7 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
|||||||
|
|
||||||
irValue *v = ir_add_local_generated(proc, tuple);
|
irValue *v = ir_add_local_generated(proc, tuple);
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (is_ptr) {
|
if (is_ptr) {
|
||||||
Type *src = base_type(type_deref(src_type));
|
Type *src = base_type(type_deref(src_type));
|
||||||
Type *src_ptr = src_type;
|
Type *src_ptr = src_type;
|
||||||
@@ -3217,8 +3218,8 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
|||||||
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value));
|
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value));
|
||||||
irValue *dst_tag = nullptr;
|
irValue *dst_tag = nullptr;
|
||||||
for (isize i = 1; i < src->Record.variant_count; i++) {
|
for (isize i = 1; i < src->Record.variant_count; i++) {
|
||||||
Entity *f = src->Record.variants[i];
|
Type *vt = src->Record.variants[i];
|
||||||
if (are_types_identical(f->type, dst)) {
|
if (are_types_identical(vt, dst)) {
|
||||||
dst_tag = ir_const_int(a, i);
|
dst_tag = ir_const_int(a, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3252,8 +3253,8 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
|||||||
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
||||||
irValue *dst_tag = nullptr;
|
irValue *dst_tag = nullptr;
|
||||||
for (isize i = 1; i < src->Record.variant_count; i++) {
|
for (isize i = 1; i < src->Record.variant_count; i++) {
|
||||||
Entity *f = src->Record.variants[i];
|
Type *vt = src->Record.variants[i];
|
||||||
if (are_types_identical(f->type, dst)) {
|
if (are_types_identical(vt, dst)) {
|
||||||
dst_tag = ir_const_int(a, i);
|
dst_tag = ir_const_int(a, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3276,7 +3277,44 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
|
|||||||
ir_emit_jump(proc, end_block);
|
ir_emit_jump(proc, end_block);
|
||||||
ir_start_block(proc, end_block);
|
ir_start_block(proc, end_block);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (is_ptr) {
|
||||||
|
value = ir_emit_load(proc, value);
|
||||||
|
}
|
||||||
|
Type *src = base_type(type_deref(src_type));
|
||||||
|
GB_ASSERT(is_type_union(src));
|
||||||
|
Type *dst = tuple->Tuple.variables[0]->type;
|
||||||
|
Type *dst_ptr = make_type_pointer(a, dst);
|
||||||
|
|
||||||
|
irValue *value_ = ir_address_from_load_or_generate_local(proc, value);
|
||||||
|
|
||||||
|
irValue *tag = ir_emit_load(proc, ir_emit_union_tag_ptr(proc, value_));
|
||||||
|
irValue *dst_tag = nullptr;
|
||||||
|
for (isize i = 1; i < src->Record.variant_count; i++) {
|
||||||
|
Type *vt = src->Record.variants[i];
|
||||||
|
if (are_types_identical(vt, dst)) {
|
||||||
|
dst_tag = ir_const_int(a, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GB_ASSERT(dst_tag != nullptr);
|
||||||
|
|
||||||
|
irBlock *ok_block = ir_new_block(proc, nullptr, "union_cast.ok");
|
||||||
|
irBlock *end_block = ir_new_block(proc, nullptr, "union_cast.end");
|
||||||
|
irValue *cond = ir_emit_comp(proc, Token_CmpEq, tag, dst_tag);
|
||||||
|
ir_emit_if(proc, cond, ok_block, end_block);
|
||||||
|
ir_start_block(proc, ok_block);
|
||||||
|
|
||||||
|
irValue *gep0 = ir_emit_struct_ep(proc, v, 0);
|
||||||
|
irValue *gep1 = ir_emit_struct_ep(proc, v, 1);
|
||||||
|
|
||||||
|
irValue *data = ir_emit_load(proc, ir_emit_conv(proc, value_, ir_type(gep0)));
|
||||||
|
ir_emit_store(proc, gep0, data);
|
||||||
|
ir_emit_store(proc, gep1, v_true);
|
||||||
|
|
||||||
|
ir_emit_jump(proc, end_block);
|
||||||
|
ir_start_block(proc, end_block);
|
||||||
|
#endif
|
||||||
if (!is_tuple) {
|
if (!is_tuple) {
|
||||||
// NOTE(bill): Panic on invalid conversion
|
// NOTE(bill): Panic on invalid conversion
|
||||||
Type *dst_type = tuple->Tuple.variables[0]->type;
|
Type *dst_type = tuple->Tuple.variables[0]->type;
|
||||||
@@ -6789,8 +6827,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
Type *ut = base_type(type_deref(parent_type));
|
Type *ut = base_type(type_deref(parent_type));
|
||||||
GB_ASSERT(ut->Record.kind == TypeRecord_Union);
|
GB_ASSERT(ut->Record.kind == TypeRecord_Union);
|
||||||
for (isize variant_index = 1; variant_index < ut->Record.variant_count; variant_index++) {
|
for (isize variant_index = 1; variant_index < ut->Record.variant_count; variant_index++) {
|
||||||
Entity *f = ut->Record.variants[variant_index];
|
Type *vt = ut->Record.variants[variant_index];
|
||||||
if (are_types_identical(f->type, bt)) {
|
if (are_types_identical(vt, bt)) {
|
||||||
index = ir_const_int(allocator, variant_index);
|
index = ir_const_int(allocator, variant_index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -7782,6 +7820,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
irValue *tag = nullptr;
|
irValue *tag = nullptr;
|
||||||
irValue *ti_ptr = ir_emit_array_epi(proc, ir_global_type_info_data, entry_index);
|
irValue *ti_ptr = ir_emit_array_epi(proc, ir_global_type_info_data, entry_index);
|
||||||
|
irValue *variant_ptr = ir_emit_struct_ep(proc, ti_ptr, 2);
|
||||||
|
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, ti_ptr, 0), ir_const_int(a, type_size_of(a, t)));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, ti_ptr, 0), ir_const_int(a, type_size_of(a, t)));
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, ti_ptr, 1), ir_const_int(a, type_align_of(a, t)));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, ti_ptr, 1), ir_const_int(a, type_align_of(a, t)));
|
||||||
@@ -7790,21 +7829,21 @@ void ir_gen_tree(irGen *s) {
|
|||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Named: {
|
case Type_Named: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoNamed"));
|
ir_emit_comment(proc, str_lit("TypeInfoNamed"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_named_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_named_ptr);
|
||||||
|
|
||||||
// TODO(bill): Which is better? The mangled name or actual name?
|
// TODO(bill): Which is better? The mangled name or actual name?
|
||||||
irValue *name = ir_const_string(a, t->Named.type_name->token.string);
|
irValue *name = ir_const_string(a, t->Named.type_name->token.string);
|
||||||
irValue *gtip = ir_get_type_info_ptr(proc, t->Named.base);
|
irValue *gtip = ir_get_type_info_ptr(proc, t->Named.base);
|
||||||
|
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), name);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), name);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), gtip);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), gtip);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoBasic"));
|
ir_emit_comment(proc, str_lit("TypeInfoBasic"));
|
||||||
switch (t->Basic.kind) {
|
switch (t->Basic.kind) {
|
||||||
case Basic_bool:
|
case Basic_bool:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_boolean_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_boolean_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Basic_i8:
|
case Basic_i8:
|
||||||
@@ -7819,106 +7858,106 @@ void ir_gen_tree(irGen *s) {
|
|||||||
case Basic_u128:
|
case Basic_u128:
|
||||||
case Basic_int:
|
case Basic_int:
|
||||||
case Basic_uint: {
|
case Basic_uint: {
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_integer_ptr);
|
||||||
irValue *is_signed = ir_const_bool(a, (t->Basic.flags & BasicFlag_Unsigned) == 0);
|
irValue *is_signed = ir_const_bool(a, (t->Basic.flags & BasicFlag_Unsigned) == 0);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), is_signed);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), is_signed);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Basic_rune:
|
case Basic_rune:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_rune_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_rune_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case Basic_f16:
|
// case Basic_f16:
|
||||||
case Basic_f32:
|
case Basic_f32:
|
||||||
case Basic_f64:
|
case Basic_f64:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_float_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_float_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case Basic_complex32:
|
// case Basic_complex32:
|
||||||
case Basic_complex64:
|
case Basic_complex64:
|
||||||
case Basic_complex128:
|
case Basic_complex128:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_complex_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_complex_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Basic_rawptr:
|
case Basic_rawptr:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_pointer_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Basic_string:
|
case Basic_string:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_string_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_string_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Basic_any:
|
case Basic_any:
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_any_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_any_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_Pointer: {
|
case Type_Pointer: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoPointer"));
|
ir_emit_comment(proc, str_lit("TypeInfoPointer"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_pointer_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_pointer_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, t->Pointer.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, t->Pointer.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
} break;
|
} break;
|
||||||
case Type_Atomic: {
|
case Type_Atomic: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoAtomic"));
|
ir_emit_comment(proc, str_lit("TypeInfoAtomic"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_atomic_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_atomic_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, t->Atomic.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, t->Atomic.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
} break;
|
} break;
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoArray"));
|
ir_emit_comment(proc, str_lit("TypeInfoArray"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_array_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, t->Array.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, t->Array.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
|
|
||||||
isize ez = type_size_of(a, t->Array.elem);
|
isize ez = type_size_of(a, t->Array.elem);
|
||||||
irValue *elem_size = ir_emit_struct_ep(proc, tag, 3);
|
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
||||||
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
||||||
|
|
||||||
irValue *count = ir_emit_struct_ep(proc, tag, 4);
|
irValue *count = ir_emit_struct_ep(proc, tag, 2);
|
||||||
ir_emit_store(proc, count, ir_const_int(a, t->Array.count));
|
ir_emit_store(proc, count, ir_const_int(a, t->Array.count));
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Type_DynamicArray: {
|
case Type_DynamicArray: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoDynamicArray"));
|
ir_emit_comment(proc, str_lit("TypeInfoDynamicArray"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_dynamic_array_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_dynamic_array_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, t->DynamicArray.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, t->DynamicArray.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
|
|
||||||
isize ez = type_size_of(a, t->DynamicArray.elem);
|
isize ez = type_size_of(a, t->DynamicArray.elem);
|
||||||
irValue *elem_size = ir_emit_struct_ep(proc, tag, 3);
|
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
||||||
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
||||||
} break;
|
} break;
|
||||||
case Type_Slice: {
|
case Type_Slice: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoSlice"));
|
ir_emit_comment(proc, str_lit("TypeInfoSlice"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_slice_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_slice_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, t->Slice.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, t->Slice.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
|
|
||||||
isize ez = type_size_of(a, t->Slice.elem);
|
isize ez = type_size_of(a, t->Slice.elem);
|
||||||
irValue *elem_size = ir_emit_struct_ep(proc, tag, 3);
|
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
||||||
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
ir_emit_store(proc, elem_size, ir_const_int(a, ez));
|
||||||
} break;
|
} break;
|
||||||
case Type_Vector: {
|
case Type_Vector: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoVector"));
|
ir_emit_comment(proc, str_lit("TypeInfoVector"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_vector_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_vector_ptr);
|
||||||
irValue *gep = ir_get_type_info_ptr(proc, t->Vector.elem);
|
irValue *gep = ir_get_type_info_ptr(proc, t->Vector.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), gep);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
||||||
|
|
||||||
isize ez = type_size_of(a, t->Vector.elem);
|
isize ez = type_size_of(a, t->Vector.elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_const_int(a, ez));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), ir_const_int(a, ez));
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), ir_const_int(a, t->Vector.count));
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_const_int(a, t->Vector.count));
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Type_Proc: {
|
case Type_Proc: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoProc"));
|
ir_emit_comment(proc, str_lit("TypeInfoProc"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_procedure_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_procedure_ptr);
|
||||||
|
|
||||||
irValue *params = ir_emit_struct_ep(proc, tag, 2);
|
irValue *params = ir_emit_struct_ep(proc, tag, 0);
|
||||||
irValue *results = ir_emit_struct_ep(proc, tag, 3);
|
irValue *results = ir_emit_struct_ep(proc, tag, 1);
|
||||||
irValue *variadic = ir_emit_struct_ep(proc, tag, 4);
|
irValue *variadic = ir_emit_struct_ep(proc, tag, 2);
|
||||||
irValue *convention = ir_emit_struct_ep(proc, tag, 5);
|
irValue *convention = ir_emit_struct_ep(proc, tag, 3);
|
||||||
|
|
||||||
if (t->Proc.params != nullptr) {
|
if (t->Proc.params != nullptr) {
|
||||||
ir_emit_store(proc, params, ir_get_type_info_ptr(proc, t->Proc.params));
|
ir_emit_store(proc, params, ir_get_type_info_ptr(proc, t->Proc.params));
|
||||||
@@ -7933,8 +7972,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
} break;
|
} break;
|
||||||
case Type_Tuple: {
|
case Type_Tuple: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoTuple"));
|
ir_emit_comment(proc, str_lit("TypeInfoTuple"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_tuple_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_tuple_ptr);
|
||||||
irValue *record = ir_emit_struct_ep(proc, tag, 2);
|
|
||||||
|
|
||||||
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Tuple.variable_count);
|
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Tuple.variable_count);
|
||||||
irValue *memory_names = ir_type_info_member_names_offset(proc, t->Tuple.variable_count);
|
irValue *memory_names = ir_type_info_member_names_offset(proc, t->Tuple.variable_count);
|
||||||
@@ -7954,23 +7992,22 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *count = ir_const_int(a, t->Tuple.variable_count);
|
irValue *count = ir_const_int(a, t->Tuple.variable_count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count);
|
||||||
} break;
|
} break;
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
switch (t->Record.kind) {
|
||||||
case TypeRecord_Struct: {
|
case TypeRecord_Struct: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoStruct"));
|
ir_emit_comment(proc, str_lit("TypeInfoStruct"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_struct_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_struct_ptr);
|
||||||
irValue *record = ir_emit_struct_ep(proc, tag, 2);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
irValue *packed = ir_const_bool(a, t->Record.is_packed);
|
irValue *packed = ir_const_bool(a, t->Record.is_packed);
|
||||||
irValue *ordered = ir_const_bool(a, t->Record.is_ordered);
|
irValue *ordered = ir_const_bool(a, t->Record.is_ordered);
|
||||||
irValue *custom_align = ir_const_bool(a, t->Record.custom_align != 0);
|
irValue *custom_align = ir_const_bool(a, t->Record.custom_align != 0);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), packed);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), packed);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, record, 5), ordered);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 5), ordered);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, record, 6), custom_align);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 6), custom_align);
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count);
|
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count);
|
||||||
@@ -8001,17 +8038,17 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *count = ir_const_int(a, t->Record.field_count);
|
irValue *count = ir_const_int(a, t->Record.field_count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 3), memory_usings, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 3), memory_usings, count, count);
|
||||||
} break;
|
} break;
|
||||||
case TypeRecord_Union: {
|
case TypeRecord_Union: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoUnion"));
|
ir_emit_comment(proc, str_lit("TypeInfoUnion"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_union_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_union_ptr);
|
||||||
|
|
||||||
{
|
{
|
||||||
irValue *common_fields = ir_emit_struct_ep(proc, tag, 2);
|
irValue *common_fields = ir_emit_struct_ep(proc, tag, 0);
|
||||||
|
|
||||||
isize field_count = t->Record.field_count;
|
isize field_count = t->Record.field_count;
|
||||||
irValue *memory_types = ir_type_info_member_types_offset(proc, field_count);
|
irValue *memory_types = ir_type_info_member_types_offset(proc, field_count);
|
||||||
@@ -8046,8 +8083,8 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
irValue *variant_names = ir_emit_struct_ep(proc, tag, 3);
|
irValue *variant_names = ir_emit_struct_ep(proc, tag, 1);
|
||||||
irValue *variant_types = ir_emit_struct_ep(proc, tag, 4);
|
irValue *variant_types = ir_emit_struct_ep(proc, tag, 2);
|
||||||
|
|
||||||
isize variant_count = gb_max(0, t->Record.variant_count-1);
|
isize variant_count = gb_max(0, t->Record.variant_count-1);
|
||||||
irValue *memory_names = ir_type_info_member_names_offset(proc, variant_count);
|
irValue *memory_names = ir_type_info_member_names_offset(proc, variant_count);
|
||||||
@@ -8055,17 +8092,12 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
// NOTE(bill): Zeroth is nil so ignore it
|
// NOTE(bill): Zeroth is nil so ignore it
|
||||||
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
|
for (isize variant_index = 0; variant_index < variant_count; variant_index++) {
|
||||||
Entity *f = t->Record.variants[variant_index+1]; // Skip zeroth
|
Type *vt = t->Record.variants[variant_index+1]; // Skip zeroth
|
||||||
irValue *tip = ir_get_type_info_ptr(proc, f->type);
|
irValue *tip = ir_get_type_info_ptr(proc, vt);
|
||||||
|
|
||||||
irValue *index = ir_const_int(a, variant_index);
|
irValue *index = ir_const_int(a, variant_index);
|
||||||
irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index);
|
irValue *type_info = ir_emit_ptr_offset(proc, memory_types, index);
|
||||||
ir_emit_store(proc, type_info, ir_type_info(proc, f->type));
|
ir_emit_store(proc, type_info, ir_type_info(proc, vt));
|
||||||
|
|
||||||
if (f->token.string.len > 0) {
|
|
||||||
irValue *name = ir_emit_ptr_offset(proc, memory_names, index);
|
|
||||||
ir_emit_store(proc, name, ir_const_string(a, f->token.string));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *count = ir_const_int(a, variant_count);
|
irValue *count = ir_const_int(a, variant_count);
|
||||||
@@ -8076,8 +8108,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
} break;
|
} break;
|
||||||
case TypeRecord_RawUnion: {
|
case TypeRecord_RawUnion: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoRawUnion"));
|
ir_emit_comment(proc, str_lit("TypeInfoRawUnion"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_raw_union_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_raw_union_ptr);
|
||||||
irValue *record = ir_emit_struct_ep(proc, tag, 2);
|
|
||||||
|
|
||||||
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count);
|
irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count);
|
||||||
irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count);
|
irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count);
|
||||||
@@ -8097,17 +8128,17 @@ void ir_gen_tree(irGen *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *count = ir_const_int(a, t->Record.field_count);
|
irValue *count = ir_const_int(a, t->Record.field_count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 0), memory_types, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 1), memory_names, count, count);
|
||||||
ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
|
ir_fill_slice(proc, ir_emit_struct_ep(proc, tag, 2), memory_offsets, count, count);
|
||||||
} break;
|
} break;
|
||||||
case TypeRecord_Enum:
|
case TypeRecord_Enum:
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoEnum"));
|
ir_emit_comment(proc, str_lit("TypeInfoEnum"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_enum_ptr);
|
||||||
{
|
{
|
||||||
GB_ASSERT(t->Record.enum_base_type != nullptr);
|
GB_ASSERT(t->Record.enum_base_type != nullptr);
|
||||||
irValue *base = ir_type_info(proc, t->Record.enum_base_type);
|
irValue *base = ir_type_info(proc, t->Record.enum_base_type);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), base);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), base);
|
||||||
|
|
||||||
if (t->Record.field_count > 0) {
|
if (t->Record.field_count > 0) {
|
||||||
Entity **fields = t->Record.fields;
|
Entity **fields = t->Record.fields;
|
||||||
@@ -8140,11 +8171,11 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
irValue *v_count = ir_const_int(a, count);
|
irValue *v_count = ir_const_int(a, count);
|
||||||
|
|
||||||
irValue *names = ir_emit_struct_ep(proc, tag, 3);
|
irValue *names = ir_emit_struct_ep(proc, tag, 1);
|
||||||
irValue *name_array_elem = ir_array_elem(proc, name_array);
|
irValue *name_array_elem = ir_array_elem(proc, name_array);
|
||||||
ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
|
ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
|
||||||
|
|
||||||
irValue *values = ir_emit_struct_ep(proc, tag, 4);
|
irValue *values = ir_emit_struct_ep(proc, tag, 2);
|
||||||
irValue *value_array_elem = ir_array_elem(proc, value_array);
|
irValue *value_array_elem = ir_array_elem(proc, value_array);
|
||||||
ir_fill_slice(proc, values, value_array_elem, v_count, v_count);
|
ir_fill_slice(proc, values, value_array_elem, v_count, v_count);
|
||||||
}
|
}
|
||||||
@@ -8154,12 +8185,12 @@ void ir_gen_tree(irGen *s) {
|
|||||||
} break;
|
} break;
|
||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoMap"));
|
ir_emit_comment(proc, str_lit("TypeInfoMap"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_map_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_map_ptr);
|
||||||
|
|
||||||
irValue *key = ir_emit_struct_ep(proc, tag, 2);
|
irValue *key = ir_emit_struct_ep(proc, tag, 0);
|
||||||
irValue *value = ir_emit_struct_ep(proc, tag, 3);
|
irValue *value = ir_emit_struct_ep(proc, tag, 1);
|
||||||
irValue *generated_struct = ir_emit_struct_ep(proc, tag, 4);
|
irValue *generated_struct = ir_emit_struct_ep(proc, tag, 2);
|
||||||
irValue *count = ir_emit_struct_ep(proc, tag, 5);
|
irValue *count = ir_emit_struct_ep(proc, tag, 3);
|
||||||
|
|
||||||
ir_emit_store(proc, key, ir_get_type_info_ptr(proc, t->Map.key));
|
ir_emit_store(proc, key, ir_get_type_info_ptr(proc, t->Map.key));
|
||||||
ir_emit_store(proc, value, ir_get_type_info_ptr(proc, t->Map.value));
|
ir_emit_store(proc, value, ir_get_type_info_ptr(proc, t->Map.value));
|
||||||
@@ -8169,7 +8200,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
case Type_BitField: {
|
case Type_BitField: {
|
||||||
ir_emit_comment(proc, str_lit("TypeInfoBitField"));
|
ir_emit_comment(proc, str_lit("TypeInfoBitField"));
|
||||||
tag = ir_emit_conv(proc, ti_ptr, t_type_info_map_ptr);
|
tag = ir_emit_conv(proc, variant_ptr, t_type_info_map_ptr);
|
||||||
// names: []string,
|
// names: []string,
|
||||||
// bits: []u32,
|
// bits: []u32,
|
||||||
// offsets: []u32,
|
// offsets: []u32,
|
||||||
@@ -8196,15 +8227,15 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
irValue *v_count = ir_const_int(a, count);
|
irValue *v_count = ir_const_int(a, count);
|
||||||
|
|
||||||
irValue *names = ir_emit_struct_ep(proc, tag, 3);
|
irValue *names = ir_emit_struct_ep(proc, tag, 1);
|
||||||
irValue *name_array_elem = ir_array_elem(proc, name_array);
|
irValue *name_array_elem = ir_array_elem(proc, name_array);
|
||||||
ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
|
ir_fill_slice(proc, names, name_array_elem, v_count, v_count);
|
||||||
|
|
||||||
irValue *bits = ir_emit_struct_ep(proc, tag, 4);
|
irValue *bits = ir_emit_struct_ep(proc, tag, 2);
|
||||||
irValue *bit_array_elem = ir_array_elem(proc, bit_array);
|
irValue *bit_array_elem = ir_array_elem(proc, bit_array);
|
||||||
ir_fill_slice(proc, bits, bit_array_elem, v_count, v_count);
|
ir_fill_slice(proc, bits, bit_array_elem, v_count, v_count);
|
||||||
|
|
||||||
irValue *offsets = ir_emit_struct_ep(proc, tag, 5);
|
irValue *offsets = ir_emit_struct_ep(proc, tag, 3);
|
||||||
irValue *offset_array_elem = ir_array_elem(proc, offset_array);
|
irValue *offset_array_elem = ir_array_elem(proc, offset_array);
|
||||||
ir_fill_slice(proc, offsets, offset_array_elem, v_count, v_count);
|
ir_fill_slice(proc, offsets, offset_array_elem, v_count, v_count);
|
||||||
}
|
}
|
||||||
@@ -8216,18 +8247,20 @@ void ir_gen_tree(irGen *s) {
|
|||||||
Type *tag_type = type_deref(ir_type(tag));
|
Type *tag_type = type_deref(ir_type(tag));
|
||||||
GB_ASSERT(is_type_named(tag_type));
|
GB_ASSERT(is_type_named(tag_type));
|
||||||
Type *ti = base_type(t_type_info);
|
Type *ti = base_type(t_type_info);
|
||||||
|
Type *tiv = base_type(ti->Record.fields_in_src_order[2]->type);
|
||||||
|
GB_ASSERT(is_type_union(tiv));
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (isize i = 1; i < ti->Record.variant_count; i++) {
|
for (isize i = 1; i < tiv->Record.variant_count; i++) {
|
||||||
Entity *f = ti->Record.variants[i];
|
Type *vt = tiv->Record.variants[i];
|
||||||
if (are_types_identical(f->type, tag_type)) {
|
if (are_types_identical(vt, tag_type)) {
|
||||||
found = true;
|
found = true;
|
||||||
irValue *tag = ir_const_int(a, i);
|
irValue *tag_val = ir_const_int(a, i);
|
||||||
irValue *ptr = ir_emit_union_tag_ptr(proc, ti_ptr);
|
irValue *ptr = ir_emit_union_tag_ptr(proc, variant_ptr);
|
||||||
ir_emit_store(proc, ptr, tag);
|
ir_emit_store(proc, ptr, tag_val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GB_ASSERT_MSG(found, "%s", type_to_string(tag_type));
|
GB_ASSERT_MSG(found, "Tag type not found: %s", type_to_string(tag_type));
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t));
|
GB_PANIC("Unhandled TypeInfo type: %s", type_to_string(t));
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-45
@@ -425,8 +425,6 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
|
|||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(UnionType, "union type", struct { \
|
AST_NODE_KIND(UnionType, "union type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Array<AstNode *> fields; \
|
|
||||||
isize field_count; \
|
|
||||||
Array<AstNode *> variants; \
|
Array<AstNode *> variants; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(RawUnionType, "raw union type", struct { \
|
AST_NODE_KIND(RawUnionType, "raw union type", struct { \
|
||||||
@@ -864,7 +862,6 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
|
|||||||
n->StructType.align = clone_ast_node(a, n->StructType.align);
|
n->StructType.align = clone_ast_node(a, n->StructType.align);
|
||||||
break;
|
break;
|
||||||
case AstNode_UnionType:
|
case AstNode_UnionType:
|
||||||
n->UnionType.fields = clone_ast_node_array(a, n->UnionType.fields);
|
|
||||||
n->UnionType.variants = clone_ast_node_array(a, n->UnionType.variants);
|
n->UnionType.variants = clone_ast_node_array(a, n->UnionType.variants);
|
||||||
break;
|
break;
|
||||||
case AstNode_RawUnionType:
|
case AstNode_RawUnionType:
|
||||||
@@ -1459,11 +1456,9 @@ AstNode *ast_struct_type(AstFile *f, Token token, Array<AstNode *> fields, isize
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *ast_union_type(AstFile *f, Token token, Array<AstNode *> fields, isize field_count, Array<AstNode *> variants) {
|
AstNode *ast_union_type(AstFile *f, Token token, Array<AstNode *> variants) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_UnionType);
|
AstNode *result = make_ast_node(f, AstNode_UnionType);
|
||||||
result->UnionType.token = token;
|
result->UnionType.token = token;
|
||||||
result->UnionType.fields = fields;
|
|
||||||
result->UnionType.field_count = field_count;
|
|
||||||
result->UnionType.variants = variants;
|
result->UnionType.variants = variants;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -3707,7 +3702,6 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|||||||
case Token_union: {
|
case Token_union: {
|
||||||
Token token = expect_token(f, Token_union);
|
Token token = expect_token(f, Token_union);
|
||||||
Token open = expect_token_after(f, Token_OpenBrace, "union");
|
Token open = expect_token_after(f, Token_OpenBrace, "union");
|
||||||
Array<AstNode *> decls = make_ast_node_array(f);
|
|
||||||
Array<AstNode *> variants = make_ast_node_array(f);
|
Array<AstNode *> variants = make_ast_node_array(f);
|
||||||
isize total_decl_name_count = 0;
|
isize total_decl_name_count = 0;
|
||||||
|
|
||||||
@@ -3717,50 +3711,18 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|||||||
|
|
||||||
while (f->curr_token.kind != Token_CloseBrace &&
|
while (f->curr_token.kind != Token_CloseBrace &&
|
||||||
f->curr_token.kind != Token_EOF) {
|
f->curr_token.kind != Token_EOF) {
|
||||||
CommentGroup docs = f->lead_comment;
|
AstNode *type = parse_type(f);
|
||||||
u32 flags = parse_field_prefixes(f);
|
if (type->kind != AstNode_BadExpr) {
|
||||||
auto names = parse_ident_list(f);
|
array_add(&variants, type);
|
||||||
if (names.count == 0) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
u32 set_flags = check_field_prefixes(f, names.count, FieldFlag_using, flags);
|
if (!allow_token(f, Token_Comma)) {
|
||||||
if (names.count == 1 && f->curr_token.kind == Token_OpenBrace) {
|
break;
|
||||||
if (set_flags != 0) {
|
|
||||||
error(names[0], "Variants cannot have field prefixes");
|
|
||||||
set_flags = 0;
|
|
||||||
}
|
|
||||||
AstNode *name = names[0];
|
|
||||||
Token open = expect_token(f, Token_OpenBrace);
|
|
||||||
isize decl_count = 0;
|
|
||||||
AstNode *list = parse_record_field_list(f, &decl_count);
|
|
||||||
Token close = expect_token(f, Token_CloseBrace);
|
|
||||||
|
|
||||||
array_add(&variants, ast_union_field(f, name, list));
|
|
||||||
expect_semicolon(f, nullptr);
|
|
||||||
} else {
|
|
||||||
AstNode *decl = parse_value_decl(f, names, docs);
|
|
||||||
if (decl->kind != AstNode_ValueDecl) {
|
|
||||||
error(decl, "Expected a field list, got %.*s", LIT(ast_node_strings[decl->kind]));
|
|
||||||
} else {
|
|
||||||
ast_node(vd, ValueDecl, decl);
|
|
||||||
if (vd->is_mutable) {
|
|
||||||
if (set_flags&FieldFlag_using) {
|
|
||||||
vd->flags |= VarDeclFlag_using;
|
|
||||||
}
|
|
||||||
if (vd->flags&VarDeclFlag_thread_local) {
|
|
||||||
vd->flags &= ~VarDeclFlag_thread_local;
|
|
||||||
error(decl, "Field values cannot be #thread_local");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
array_add(&decls, decl);
|
|
||||||
total_decl_name_count += vd->names.count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token close = expect_token(f, Token_CloseBrace);
|
Token close = expect_token(f, Token_CloseBrace);
|
||||||
|
|
||||||
return ast_union_type(f, token, decls, total_decl_name_count, variants);
|
return ast_union_type(f, token, variants);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Token_raw_union: {
|
case Token_raw_union: {
|
||||||
|
|||||||
+8
-38
@@ -93,7 +93,7 @@ struct TypeRecord {
|
|||||||
Scope * scope;
|
Scope * scope;
|
||||||
|
|
||||||
// Entity_TypeName - union
|
// Entity_TypeName - union
|
||||||
Entity **variants;
|
Type ** variants;
|
||||||
i32 variant_count;
|
i32 variant_count;
|
||||||
Entity * union__tag;
|
Entity * union__tag;
|
||||||
i64 variant_block_size; // NOTE(bill): Internal use only
|
i64 variant_block_size; // NOTE(bill): Internal use only
|
||||||
@@ -1002,7 +1002,7 @@ bool is_type_polymorphic(Type *t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (isize i = 1; i < t->Record.variant_count; i++) {
|
for (isize i = 1; i < t->Record.variant_count; i++) {
|
||||||
if (is_type_polymorphic(t->Record.variants[i]->type)) {
|
if (is_type_polymorphic(t->Record.variants[i])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1163,10 +1163,7 @@ bool are_types_identical(Type *x, Type *y) {
|
|||||||
}
|
}
|
||||||
// NOTE(bill): zeroth variant is nullptr
|
// NOTE(bill): zeroth variant is nullptr
|
||||||
for (isize i = 1; i < x->Record.variant_count; i++) {
|
for (isize i = 1; i < x->Record.variant_count; i++) {
|
||||||
if (!are_types_identical(x->Record.variants[i]->type, y->Record.variants[i]->type)) {
|
if (!are_types_identical(x->Record.variants[i], y->Record.variants[i])) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (x->Record.variants[i]->token.string != y->Record.variants[i]->token.string) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1555,19 +1552,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type_union(type)) {
|
if (is_type_enum(type)) {
|
||||||
for (isize i = 1; i < type->Record.variant_count; i++) {
|
|
||||||
Entity *f = type->Record.variants[i];
|
|
||||||
GB_ASSERT(f->kind == Entity_TypeName);
|
|
||||||
String str = f->token.string;
|
|
||||||
|
|
||||||
if (str == field_name) {
|
|
||||||
sel.entity = f;
|
|
||||||
// selection_add_index(&sel, i);
|
|
||||||
return sel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (is_type_enum(type)) {
|
|
||||||
// NOTE(bill): These may not have been added yet, so check in case
|
// NOTE(bill): These may not have been added yet, so check in case
|
||||||
if (type->Record.enum_count != nullptr) {
|
if (type->Record.enum_count != nullptr) {
|
||||||
if (field_name == "count") {
|
if (field_name == "count") {
|
||||||
@@ -1880,7 +1865,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
}
|
}
|
||||||
// NOTE(bill): field zero is null
|
// NOTE(bill): field zero is null
|
||||||
for (isize i = 1; i < t->Record.variant_count; i++) {
|
for (isize i = 1; i < t->Record.variant_count; i++) {
|
||||||
Type *variant = t->Record.variants[i]->type;
|
Type *variant = t->Record.variants[i];
|
||||||
type_path_push(path, variant);
|
type_path_push(path, variant);
|
||||||
if (path->failure) {
|
if (path->failure) {
|
||||||
return FAILURE_ALIGNMENT;
|
return FAILURE_ALIGNMENT;
|
||||||
@@ -2139,7 +2124,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
i64 field_size = max;
|
i64 field_size = max;
|
||||||
|
|
||||||
for (isize i = 1; i < variant_count; i++) {
|
for (isize i = 1; i < variant_count; i++) {
|
||||||
Type *variant_type = t->Record.variants[i]->type;
|
Type *variant_type = t->Record.variants[i];
|
||||||
i64 size = type_size_of_internal(allocator, variant_type, path);
|
i64 size = type_size_of_internal(allocator, variant_type, path);
|
||||||
if (max < size) {
|
if (max < size) {
|
||||||
max = size;
|
max = size;
|
||||||
@@ -2369,26 +2354,11 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
str = write_type_to_string(str, f->type);
|
str = write_type_to_string(str, f->type);
|
||||||
}
|
}
|
||||||
for (isize i = 1; i < type->Record.variant_count; i++) {
|
for (isize i = 1; i < type->Record.variant_count; i++) {
|
||||||
Entity *f = type->Record.variants[i];
|
Type *t = type->Record.variants[i];
|
||||||
GB_ASSERT(f->kind == Entity_TypeName);
|
|
||||||
if (i > 1 || type->Record.field_count > 1) {
|
if (i > 1 || type->Record.field_count > 1) {
|
||||||
str = gb_string_appendc(str, ", ");
|
str = gb_string_appendc(str, ", ");
|
||||||
}
|
}
|
||||||
str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
|
str = write_type_to_string(str, t);
|
||||||
str = gb_string_appendc(str, "{");
|
|
||||||
Type *variant = base_type(f->type);
|
|
||||||
for (isize i = 0; i < variant->Record.field_count; i++) {
|
|
||||||
Entity *f = variant->Record.fields[i];
|
|
||||||
GB_ASSERT(f->kind == Entity_Variable);
|
|
||||||
if (i > 0) {
|
|
||||||
str = gb_string_appendc(str, ", ");
|
|
||||||
}
|
|
||||||
str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
|
|
||||||
str = gb_string_appendc(str, ": ");
|
|
||||||
str = write_type_to_string(str, f->type);
|
|
||||||
}
|
|
||||||
str = gb_string_appendc(str, "{");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
str = gb_string_appendc(str, "}");
|
str = gb_string_appendc(str, "}");
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user