mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Untyped nil
This commit is contained in:
@@ -254,3 +254,4 @@ paket-files/
|
|||||||
*.sln
|
*.sln
|
||||||
!misc/llvm-bim/lli.exe
|
!misc/llvm-bim/lli.exe
|
||||||
!misc/llvm-bim/opt.exe
|
!misc/llvm-bim/opt.exe
|
||||||
|
builds
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ if %release_mode% EQU 0 ( rem Debug
|
|||||||
set compiler_flags=%compiler_flags% -Od -MDd -Z7
|
set compiler_flags=%compiler_flags% -Od -MDd -Z7
|
||||||
rem -DDISPLAY_TIMING
|
rem -DDISPLAY_TIMING
|
||||||
) else ( rem Release
|
) else ( rem Release
|
||||||
set compiler_flags=%compiler_flags% -O2 -MT
|
set compiler_flags=%compiler_flags% -O2 -MT -Z7
|
||||||
)
|
)
|
||||||
|
|
||||||
set compiler_warnings= ^
|
set compiler_warnings= ^
|
||||||
-we4013 -we4706 ^
|
-we4013 -we4706 -we4002 ^
|
||||||
-wd4100 -wd4127 -wd4189 ^
|
-wd4100 -wd4127 -wd4189 ^
|
||||||
-wd4201 -wd4204 -wd4244 ^
|
-wd4201 -wd4204 -wd4244 ^
|
||||||
-wd4306 ^
|
-wd4306 ^
|
||||||
-wd4480 ^
|
-wd4456 -wd4457 -wd4480 ^
|
||||||
-wd4505 -wd4512 -wd4550
|
-wd4505 -wd4512 -wd4550
|
||||||
|
|
||||||
set compiler_includes=
|
set compiler_includes=
|
||||||
@@ -31,7 +31,7 @@ set linker_flags= -incremental:no -opt:ref -subsystem:console
|
|||||||
if %release_mode% EQU 0 ( rem Debug
|
if %release_mode% EQU 0 ( rem Debug
|
||||||
set linker_flags=%linker_flags% -debug
|
set linker_flags=%linker_flags% -debug
|
||||||
) else ( rem Release
|
) else ( rem Release
|
||||||
set linker_flags=%linker_flags%
|
set linker_flags=%linker_flags% -debug
|
||||||
)
|
)
|
||||||
|
|
||||||
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
|
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
|
||||||
|
|||||||
+11
-5
@@ -1,9 +1,15 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
#import "utf8.odin"
|
|
||||||
#import "hash.odin"
|
A :: {2}f32{1, 2}
|
||||||
#import "mem.odin"
|
B :: {2}f32{3, 4}
|
||||||
#import "game.odin"
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.println("Hellope")
|
Fruit :: union {
|
||||||
|
A: int
|
||||||
|
B: f32
|
||||||
|
C: struct {
|
||||||
|
x: int
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -50,7 +50,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
|
|||||||
c_class_name := class_name.data
|
c_class_name := class_name.data
|
||||||
w.c_title = to_c_string(title)
|
w.c_title = to_c_string(title)
|
||||||
|
|
||||||
instance := GetModuleHandleA(null)
|
instance := GetModuleHandleA(nil)
|
||||||
|
|
||||||
w.wc = WNDCLASSEXA{
|
w.wc = WNDCLASSEXA{
|
||||||
size = size_of(WNDCLASSEXA) as u32,
|
size = size_of(WNDCLASSEXA) as u32,
|
||||||
@@ -70,9 +70,9 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
|
|||||||
WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
w.width as i32, w.height as i32,
|
w.width as i32, w.height as i32,
|
||||||
null, null, instance, null)
|
nil, nil, instance, nil)
|
||||||
|
|
||||||
if w.hwnd == null {
|
if w.hwnd == nil {
|
||||||
win32_print_last_error()
|
win32_print_last_error()
|
||||||
return w, false
|
return w, false
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
|
|||||||
layer_type = PFD_MAIN_PLANE,
|
layer_type = PFD_MAIN_PLANE,
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), null)
|
SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), nil)
|
||||||
w.opengl_context = wglCreateContext(w.dc)
|
w.opengl_context = wglCreateContext(w.dc)
|
||||||
wglMakeCurrent(w.dc, w.opengl_context)
|
wglMakeCurrent(w.dc, w.opengl_context)
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ run :: proc() {
|
|||||||
prev_time = curr_time
|
prev_time = curr_time
|
||||||
|
|
||||||
msg: MSG
|
msg: MSG
|
||||||
for PeekMessageA(^msg, null, 0, 0, PM_REMOVE) > 0 {
|
for PeekMessageA(^msg, nil, 0, 0, PM_REMOVE) > 0 {
|
||||||
if msg.message == WM_QUIT {
|
if msg.message == WM_QUIT {
|
||||||
running = false
|
running = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
#import "fmt.odin"
|
||||||
|
#import "utf8.odin"
|
||||||
|
#import "hash.odin"
|
||||||
|
#import "mem.odin"
|
||||||
|
|
||||||
|
main :: proc() {
|
||||||
|
{ // New Standard Library stuff
|
||||||
|
s := "Hello"
|
||||||
|
fmt.println(s,
|
||||||
|
utf8.valid_string(s),
|
||||||
|
hash.murmur64(s.data, s.count))
|
||||||
|
|
||||||
|
// utf8.odin
|
||||||
|
// hash.odin
|
||||||
|
// - crc, fnv, fnva, murmur
|
||||||
|
// mem.odin
|
||||||
|
// - Custom allocators
|
||||||
|
// - Helpers
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
arena: mem.Arena
|
||||||
|
mem.init_arena_from_context(^arena, mem.megabytes(16)) // Uses default allocator
|
||||||
|
defer mem.free_arena(^arena)
|
||||||
|
|
||||||
|
push_allocator mem.arena_allocator(^arena) {
|
||||||
|
x := new(int)
|
||||||
|
x^ = 1337
|
||||||
|
|
||||||
|
fmt.println(x^)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
push_allocator x {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
{
|
||||||
|
prev_allocator := __context.allocator
|
||||||
|
__context.allocator = x
|
||||||
|
defer __context.allocator = prev_allocator
|
||||||
|
|
||||||
|
...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// You can also "push" a context
|
||||||
|
|
||||||
|
c := current_context() // Create copy of the allocator
|
||||||
|
c.allocator = mem.arena_allocator(^arena)
|
||||||
|
|
||||||
|
push_context c {
|
||||||
|
x := new(int)
|
||||||
|
x^ = 365
|
||||||
|
|
||||||
|
fmt.println(x^)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backend improvements
|
||||||
|
// - Minimal dependency building (only build what is needed)
|
||||||
|
// - Numerous bugs fixed
|
||||||
|
// - Mild parsing recovery after bad syntax error
|
||||||
|
}
|
||||||
@@ -14,10 +14,10 @@ Type_Info :: union {
|
|||||||
}
|
}
|
||||||
Record :: struct #ordered {
|
Record :: struct #ordered {
|
||||||
fields: []Member
|
fields: []Member
|
||||||
packed: bool
|
|
||||||
ordered: bool
|
|
||||||
size: int // in bytes
|
size: int // in bytes
|
||||||
align: int // in bytes
|
align: int // in bytes
|
||||||
|
packed: bool
|
||||||
|
ordered: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
Named: struct #ordered {
|
Named: struct #ordered {
|
||||||
@@ -60,15 +60,15 @@ Type_Info :: union {
|
|||||||
Union: Record
|
Union: Record
|
||||||
Raw_Union: Record
|
Raw_Union: Record
|
||||||
Enum: struct #ordered {
|
Enum: struct #ordered {
|
||||||
base: ^Type_Info
|
base: ^Type_Info
|
||||||
values: []i64
|
values: []i64
|
||||||
names: []string
|
names: []string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||||
if info == null {
|
if info == nil {
|
||||||
return null
|
return nil
|
||||||
}
|
}
|
||||||
match type i : info {
|
match type i : info {
|
||||||
case Type_Info.Named:
|
case Type_Info.Named:
|
||||||
@@ -142,7 +142,7 @@ current_context :: proc() -> Context { // Copy of context
|
|||||||
__check_context :: proc() {
|
__check_context :: proc() {
|
||||||
c := ^__context
|
c := ^__context
|
||||||
|
|
||||||
if c.allocator.procedure == null {
|
if c.allocator.procedure == nil {
|
||||||
c.allocator = __default_allocator()
|
c.allocator = __default_allocator()
|
||||||
}
|
}
|
||||||
if c.thread_id == 0 {
|
if c.thread_id == 0 {
|
||||||
@@ -155,20 +155,20 @@ alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_AL
|
|||||||
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
|
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
|
||||||
__check_context()
|
__check_context()
|
||||||
a := current_context().allocator
|
a := current_context().allocator
|
||||||
return a.procedure(a.data, Allocator.Mode.ALLOC, size, alignment, null, 0, 0)
|
return a.procedure(a.data, Allocator.Mode.ALLOC, size, alignment, nil, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
free :: proc(ptr: rawptr) #inline {
|
free :: proc(ptr: rawptr) #inline {
|
||||||
__check_context()
|
__check_context()
|
||||||
a := current_context().allocator
|
a := current_context().allocator
|
||||||
if ptr != null {
|
if ptr != nil {
|
||||||
a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
|
a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_all :: proc() #inline {
|
free_all :: proc() #inline {
|
||||||
__check_context()
|
__check_context()
|
||||||
a := current_context().allocator
|
a := current_context().allocator
|
||||||
a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0)
|
a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, nil, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -181,13 +181,13 @@ resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr
|
|||||||
|
|
||||||
|
|
||||||
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
||||||
if old_memory == null {
|
if old_memory == nil {
|
||||||
return alloc_align(new_size, alignment)
|
return alloc_align(new_size, alignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_size == 0 {
|
if new_size == 0 {
|
||||||
free(old_memory)
|
free(old_memory)
|
||||||
return null
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_size == old_size {
|
if new_size == old_size {
|
||||||
@@ -195,8 +195,8 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
|
|||||||
}
|
}
|
||||||
|
|
||||||
new_memory := alloc_align(new_size, alignment)
|
new_memory := alloc_align(new_size, alignment)
|
||||||
if new_memory == null {
|
if new_memory == nil {
|
||||||
return null
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mem.copy(new_memory, old_memory, min(old_size, new_size));
|
mem.copy(new_memory, old_memory, min(old_size, new_size));
|
||||||
@@ -220,7 +220,7 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
|||||||
|
|
||||||
case FREE:
|
case FREE:
|
||||||
os.heap_free(mem.allocation_header(old_memory))
|
os.heap_free(mem.allocation_header(old_memory))
|
||||||
return null
|
return nil
|
||||||
|
|
||||||
case FREE_ALL:
|
case FREE_ALL:
|
||||||
// NOTE(bill): Does nothing
|
// NOTE(bill): Does nothing
|
||||||
@@ -234,13 +234,13 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
|||||||
return mem.zero(ptr, size)
|
return mem.zero(ptr, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
__default_allocator :: proc() -> Allocator {
|
__default_allocator :: proc() -> Allocator {
|
||||||
return Allocator{
|
return Allocator{
|
||||||
procedure = __default_allocator_proc,
|
procedure = __default_allocator_proc,
|
||||||
data = null,
|
data = nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+19
-15
@@ -197,7 +197,7 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||||
if ti == null { return }
|
if ti == nil { return }
|
||||||
|
|
||||||
using Type_Info
|
using Type_Info
|
||||||
match type info : ti {
|
match type info : ti {
|
||||||
@@ -230,7 +230,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
print_type_to_buffer(buf, info.elem)
|
print_type_to_buffer(buf, info.elem)
|
||||||
case Procedure:
|
case Procedure:
|
||||||
print_string_to_buffer(buf, "proc")
|
print_string_to_buffer(buf, "proc")
|
||||||
if info.params == null {
|
if info.params == nil {
|
||||||
print_string_to_buffer(buf, "()")
|
print_string_to_buffer(buf, "()")
|
||||||
} else {
|
} else {
|
||||||
count := (info.params as ^Tuple).fields.count
|
count := (info.params as ^Tuple).fields.count
|
||||||
@@ -238,7 +238,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
print_type_to_buffer(buf, info.params)
|
print_type_to_buffer(buf, info.params)
|
||||||
if count == 1 { print_string_to_buffer(buf, ")") }
|
if count == 1 { print_string_to_buffer(buf, ")") }
|
||||||
}
|
}
|
||||||
if info.results != null {
|
if info.results != nil {
|
||||||
print_string_to_buffer(buf, " -> ")
|
print_string_to_buffer(buf, " -> ")
|
||||||
print_type_to_buffer(buf, info.results)
|
print_type_to_buffer(buf, info.results)
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,11 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||||
|
if arg.type_info == nil {
|
||||||
|
print_string_to_buffer(buf, "<nil>")
|
||||||
|
return
|
||||||
|
}
|
||||||
using Type_Info
|
using Type_Info
|
||||||
match type info : arg.type_info {
|
match type info : arg.type_info {
|
||||||
case Named:
|
case Named:
|
||||||
@@ -352,7 +356,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
case Integer:
|
case Integer:
|
||||||
if info.signed {
|
if info.signed {
|
||||||
i: i64 = 0;
|
i: i64 = 0;
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
match info.size {
|
match info.size {
|
||||||
case 1: i = (arg.data as ^i8)^ as i64
|
case 1: i = (arg.data as ^i8)^ as i64
|
||||||
case 2: i = (arg.data as ^i16)^ as i64
|
case 2: i = (arg.data as ^i16)^ as i64
|
||||||
@@ -363,7 +367,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
print_i64_to_buffer(buf, i)
|
print_i64_to_buffer(buf, i)
|
||||||
} else {
|
} else {
|
||||||
i: u64 = 0;
|
i: u64 = 0;
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
match info.size {
|
match info.size {
|
||||||
case 1: i = (arg.data as ^u8)^ as u64
|
case 1: i = (arg.data as ^u8)^ as u64
|
||||||
case 2: i = (arg.data as ^u16)^ as u64
|
case 2: i = (arg.data as ^u16)^ as u64
|
||||||
@@ -376,7 +380,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
|
|
||||||
case Float:
|
case Float:
|
||||||
f: f64 = 0
|
f: f64 = 0
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
match info.size {
|
match info.size {
|
||||||
case 4: f = (arg.data as ^f32)^ as f64
|
case 4: f = (arg.data as ^f32)^ as f64
|
||||||
case 8: f = (arg.data as ^f64)^ as f64
|
case 8: f = (arg.data as ^f64)^ as f64
|
||||||
@@ -386,27 +390,27 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
|
|
||||||
case String:
|
case String:
|
||||||
s := ""
|
s := ""
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
s = (arg.data as ^string)^
|
s = (arg.data as ^string)^
|
||||||
}
|
}
|
||||||
print_string_to_buffer(buf, s)
|
print_string_to_buffer(buf, s)
|
||||||
|
|
||||||
case Boolean:
|
case Boolean:
|
||||||
v := false;
|
v := false;
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
v = (arg.data as ^bool)^
|
v = (arg.data as ^bool)^
|
||||||
}
|
}
|
||||||
print_bool_to_buffer(buf, v)
|
print_bool_to_buffer(buf, v)
|
||||||
|
|
||||||
case Pointer:
|
case Pointer:
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
if arg.type_info == type_info(^Type_Info) {
|
if arg.type_info == type_info(^Type_Info) {
|
||||||
print_type_to_buffer(buf, (arg.data as ^^Type_Info)^)
|
print_type_to_buffer(buf, (arg.data as ^^Type_Info)^)
|
||||||
} else {
|
} else {
|
||||||
print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print_pointer_to_buffer(buf, null)
|
print_pointer_to_buffer(buf, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
case Enum:
|
case Enum:
|
||||||
@@ -414,7 +418,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
match type i : info.base {
|
match type i : info.base {
|
||||||
case Integer:
|
case Integer:
|
||||||
if i.signed {
|
if i.signed {
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
match i.size {
|
match i.size {
|
||||||
case 1: value = (arg.data as ^i8)^ as i64
|
case 1: value = (arg.data as ^i8)^ as i64
|
||||||
case 2: value = (arg.data as ^i16)^ as i64
|
case 2: value = (arg.data as ^i16)^ as i64
|
||||||
@@ -423,7 +427,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if arg.data != null {
|
if arg.data != nil {
|
||||||
match i.size {
|
match i.size {
|
||||||
case 1: value = (arg.data as ^u8)^ as i64
|
case 1: value = (arg.data as ^u8)^ as i64
|
||||||
case 2: value = (arg.data as ^u16)^ as i64
|
case 2: value = (arg.data as ^u16)^ as i64
|
||||||
@@ -582,7 +586,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) {
|
|||||||
is_type_string :: proc(info: ^Type_Info) -> bool {
|
is_type_string :: proc(info: ^Type_Info) -> bool {
|
||||||
using Type_Info
|
using Type_Info
|
||||||
info = type_info_base(info)
|
info = type_info_base(info)
|
||||||
if info == null {
|
if info == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,7 +601,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) {
|
|||||||
prev_string := false
|
prev_string := false
|
||||||
for i := 0; i < args.count; i++ {
|
for i := 0; i < args.count; i++ {
|
||||||
arg := args[i]
|
arg := args[i]
|
||||||
is_string := arg.data != null && is_type_string(arg.type_info)
|
is_string := arg.data != nil && is_type_string(arg.type_info)
|
||||||
if i > 0 && !is_string && !prev_string {
|
if i > 0 && !is_string && !prev_string {
|
||||||
print_space_to_buffer(buf)
|
print_space_to_buffer(buf)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -143,7 +143,7 @@ init_sub_arena :: proc(sub, parent: ^Arena, size: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
free_arena :: proc(using a: ^Arena) {
|
free_arena :: proc(using a: ^Arena) {
|
||||||
if backing.procedure != null {
|
if backing.procedure != nil {
|
||||||
push_allocator backing {
|
push_allocator backing {
|
||||||
free(memory.data)
|
free(memory.data)
|
||||||
memory = memory[0:0:0]
|
memory = memory[0:0:0]
|
||||||
@@ -170,7 +170,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
|||||||
|
|
||||||
if arena.memory.count + total_size > arena.memory.capacity {
|
if arena.memory.count + total_size > arena.memory.capacity {
|
||||||
fmt.fprintln(os.stderr, "Arena out of memory")
|
fmt.fprintln(os.stderr, "Arena out of memory")
|
||||||
return null
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
#no_bounds_check end := ^arena.memory[arena.memory.count]
|
#no_bounds_check end := ^arena.memory[arena.memory.count]
|
||||||
@@ -190,7 +190,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
|||||||
return default_resize_align(old_memory, old_size, size, alignment)
|
return default_resize_align(old_memory, old_size, size, alignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_temp_arena_memory :: proc(a: ^Arena) -> Temp_Arena_Memory {
|
begin_temp_arena_memory :: proc(a: ^Arena) -> Temp_Arena_Memory {
|
||||||
|
|||||||
+5
-5
@@ -9,7 +9,7 @@ open :: proc(name: string) -> (File, bool) {
|
|||||||
using win32
|
using win32
|
||||||
buf: [300]byte
|
buf: [300]byte
|
||||||
copy(buf[:], name as []byte)
|
copy(buf[:], name as []byte)
|
||||||
f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, 0, null)}
|
f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, nil)}
|
||||||
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
|
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
|
||||||
|
|
||||||
return f, success
|
return f, success
|
||||||
@@ -20,7 +20,7 @@ create :: proc(name: string) -> (File, bool) {
|
|||||||
buf: [300]byte
|
buf: [300]byte
|
||||||
copy(buf[:], name as []byte)
|
copy(buf[:], name as []byte)
|
||||||
f := File{
|
f := File{
|
||||||
handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, null, CREATE_ALWAYS, 0, null),
|
handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, 0, nil),
|
||||||
}
|
}
|
||||||
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
|
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
|
||||||
return f, success
|
return f, success
|
||||||
@@ -32,7 +32,7 @@ close :: proc(using f: ^File) {
|
|||||||
|
|
||||||
write :: proc(using f: ^File, buf: []byte) -> bool {
|
write :: proc(using f: ^File, buf: []byte) -> bool {
|
||||||
bytes_written: i32
|
bytes_written: i32
|
||||||
return win32.WriteFile(handle, buf.data, buf.count as i32, ^bytes_written, null) != 0
|
return win32.WriteFile(handle, buf.data, buf.count as i32, ^bytes_written, nil) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ read_entire_file :: proc(name: string) -> (string, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := new_slice(u8, length)
|
data := new_slice(u8, length)
|
||||||
if data.data == null {
|
if data.data == nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ read_entire_file :: proc(name: string) -> (string, bool) {
|
|||||||
to_read = MAX
|
to_read = MAX
|
||||||
}
|
}
|
||||||
|
|
||||||
win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, null)
|
win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, nil)
|
||||||
if single_read_length <= 0 {
|
if single_read_length <= 0 {
|
||||||
free(data.data)
|
free(data.data)
|
||||||
return "", false
|
return "", false
|
||||||
|
|||||||
+6
-6
@@ -12,14 +12,14 @@ Accept_Range :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
accept_ranges := [5]Accept_Range{
|
accept_ranges := [5]Accept_Range{
|
||||||
Accept_Range{0x80, 0xbf},
|
{0x80, 0xbf},
|
||||||
Accept_Range{0xa0, 0xbf},
|
{0xa0, 0xbf},
|
||||||
Accept_Range{0x80, 0x9f},
|
{0x80, 0x9f},
|
||||||
Accept_Range{0x90, 0xbf},
|
{0x90, 0xbf},
|
||||||
Accept_Range{0x80, 0x8f},
|
{0x80, 0x8f},
|
||||||
}
|
}
|
||||||
|
|
||||||
accept_sizes := [256]u8{
|
accept_sizes := [256]byte{
|
||||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
|
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
|
||||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
|
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
|
||||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
|
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
|
||||||
|
|||||||
@@ -1,200 +0,0 @@
|
|||||||
This file is a list of the people responsible for ensuring that patches for a
|
|
||||||
particular part of LLVM are reviewed, either by themself or by someone else.
|
|
||||||
They are also the gatekeepers for their part of LLVM, with the final word on
|
|
||||||
what goes in or not.
|
|
||||||
|
|
||||||
The list is sorted by surname and formatted to allow easy grepping and
|
|
||||||
beautification by scripts. The fields are: name (N), email (E), web-address
|
|
||||||
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
|
|
||||||
(S). Each entry should contain at least the (N), (E) and (D) fields.
|
|
||||||
|
|
||||||
N: Joe Abbey
|
|
||||||
E: jabbey@arxan.com
|
|
||||||
D: LLVM Bitcode (lib/Bitcode/* include/llvm/Bitcode/*)
|
|
||||||
|
|
||||||
N: Owen Anderson
|
|
||||||
E: resistor@mac.com
|
|
||||||
D: SelectionDAG (lib/CodeGen/SelectionDAG/*)
|
|
||||||
|
|
||||||
N: Rafael Avila de Espindola
|
|
||||||
E: rafael.espindola@gmail.com
|
|
||||||
D: Gold plugin (tools/gold/*)
|
|
||||||
|
|
||||||
N: Justin Bogner
|
|
||||||
E: mail@justinbogner.com
|
|
||||||
D: InstrProfiling and related parts of ProfileData
|
|
||||||
|
|
||||||
N: Chandler Carruth
|
|
||||||
E: chandlerc@gmail.com
|
|
||||||
E: chandlerc@google.com
|
|
||||||
D: Config, ADT, Support, inlining & related passes, SROA/mem2reg & related passes, CMake, library layering
|
|
||||||
|
|
||||||
N: Evan Cheng
|
|
||||||
E: evan.cheng@apple.com
|
|
||||||
D: parts of code generator not covered by someone else
|
|
||||||
|
|
||||||
N: Eric Christopher
|
|
||||||
E: echristo@gmail.com
|
|
||||||
D: Debug Information, autotools/configure/make build, inline assembly
|
|
||||||
|
|
||||||
N: Greg Clayton
|
|
||||||
E: gclayton@apple.com
|
|
||||||
D: LLDB
|
|
||||||
|
|
||||||
N: Marshall Clow
|
|
||||||
E: mclow.lists@gmail.com
|
|
||||||
D: libc++
|
|
||||||
|
|
||||||
N: Peter Collingbourne
|
|
||||||
E: peter@pcc.me.uk
|
|
||||||
D: llgo
|
|
||||||
|
|
||||||
N: Quentin Colombet
|
|
||||||
E: qcolombet@apple.com
|
|
||||||
D: Register allocators
|
|
||||||
|
|
||||||
N: Duncan P. N. Exon Smith
|
|
||||||
E: dexonsmith@apple.com
|
|
||||||
D: Branch weights and BlockFrequencyInfo
|
|
||||||
|
|
||||||
N: Hal Finkel
|
|
||||||
E: hfinkel@anl.gov
|
|
||||||
D: BBVectorize, the loop reroller, alias analysis and the PowerPC target
|
|
||||||
|
|
||||||
N: Dan Gohman
|
|
||||||
E: sunfish@mozilla.com
|
|
||||||
D: WebAssembly Backend (lib/Target/WebAssembly/*)
|
|
||||||
|
|
||||||
N: Renato Golin
|
|
||||||
E: renato.golin@linaro.org
|
|
||||||
D: ARM Linux support
|
|
||||||
|
|
||||||
N: Venkatraman Govindaraju
|
|
||||||
E: venkatra@cs.wisc.edu
|
|
||||||
D: Sparc Backend (lib/Target/Sparc/*)
|
|
||||||
|
|
||||||
N: Tobias Grosser
|
|
||||||
E: tobias@grosser.es
|
|
||||||
D: Polly
|
|
||||||
|
|
||||||
N: James Grosbach
|
|
||||||
E: grosbach@apple.com
|
|
||||||
D: MC layer
|
|
||||||
|
|
||||||
N: Justin Holewinski
|
|
||||||
E: jholewinski@nvidia.com
|
|
||||||
D: NVPTX Target (lib/Target/NVPTX/*)
|
|
||||||
|
|
||||||
N: Lang Hames
|
|
||||||
E: lhames@gmail.com
|
|
||||||
D: MCJIT, RuntimeDyld and JIT event listeners
|
|
||||||
|
|
||||||
N: Galina Kistanova
|
|
||||||
E: gkistanova@gmail.com
|
|
||||||
D: LLVM Buildbot
|
|
||||||
|
|
||||||
N: Anton Korobeynikov
|
|
||||||
E: anton@korobeynikov.info
|
|
||||||
D: Exception handling, Windows codegen, ARM EABI
|
|
||||||
|
|
||||||
N: Benjamin Kramer
|
|
||||||
E: benny.kra@gmail.com
|
|
||||||
D: DWARF Parser
|
|
||||||
|
|
||||||
N: Sergei Larin
|
|
||||||
E: slarin@codeaurora.org
|
|
||||||
D: VLIW Instruction Scheduling, Packetization
|
|
||||||
|
|
||||||
N: Chris Lattner
|
|
||||||
E: sabre@nondot.org
|
|
||||||
W: http://nondot.org/~sabre/
|
|
||||||
D: Everything not covered by someone else
|
|
||||||
|
|
||||||
N: David Majnemer
|
|
||||||
E: david.majnemer@gmail.com
|
|
||||||
D: IR Constant Folder, InstCombine
|
|
||||||
|
|
||||||
N: Dylan McKay
|
|
||||||
E: dylanmckay34@gmail.com
|
|
||||||
D: AVR Backend
|
|
||||||
|
|
||||||
N: Tim Northover
|
|
||||||
E: t.p.northover@gmail.com
|
|
||||||
D: AArch64 backend, misc ARM backend
|
|
||||||
|
|
||||||
N: Diego Novillo
|
|
||||||
E: dnovillo@google.com
|
|
||||||
D: SampleProfile and related parts of ProfileData
|
|
||||||
|
|
||||||
N: Jakob Olesen
|
|
||||||
E: stoklund@2pi.dk
|
|
||||||
D: TableGen
|
|
||||||
|
|
||||||
N: Richard Osborne
|
|
||||||
E: richard@xmos.com
|
|
||||||
D: XCore Backend
|
|
||||||
|
|
||||||
N: Krzysztof Parzyszek
|
|
||||||
E: kparzysz@codeaurora.org
|
|
||||||
D: Hexagon Backend
|
|
||||||
|
|
||||||
N: Paul Robinson
|
|
||||||
E: paul_robinson@playstation.sony.com
|
|
||||||
D: Sony PlayStation®4 support
|
|
||||||
|
|
||||||
N: Chad Rosier
|
|
||||||
E: mcrosier@codeaurora.org
|
|
||||||
D: Fast-Isel
|
|
||||||
|
|
||||||
N: Nadav Rotem
|
|
||||||
E: nrotem@apple.com
|
|
||||||
D: X86 Backend, Loop Vectorizer
|
|
||||||
|
|
||||||
N: Daniel Sanders
|
|
||||||
E: daniel.sanders@imgtec.com
|
|
||||||
D: MIPS Backend (lib/Target/Mips/*)
|
|
||||||
|
|
||||||
N: Duncan Sands
|
|
||||||
E: baldrick@free.fr
|
|
||||||
D: DragonEgg
|
|
||||||
|
|
||||||
N: Kostya Serebryany
|
|
||||||
E: kcc@google.com
|
|
||||||
D: AddressSanitizer, ThreadSanitizer (LLVM parts)
|
|
||||||
|
|
||||||
N: Michael Spencer
|
|
||||||
E: bigcheesegs@gmail.com
|
|
||||||
D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size
|
|
||||||
|
|
||||||
N: Alexei Starovoitov
|
|
||||||
E: alexei.starovoitov@gmail.com
|
|
||||||
D: BPF backend
|
|
||||||
|
|
||||||
N: Tom Stellard
|
|
||||||
E: thomas.stellard@amd.com
|
|
||||||
E: mesa-dev@lists.freedesktop.org
|
|
||||||
D: Release manager for the 3.5 and 3.6 branches, R600 Backend, libclc
|
|
||||||
|
|
||||||
N: Evgeniy Stepanov
|
|
||||||
E: eugenis@google.com
|
|
||||||
D: MemorySanitizer (LLVM part)
|
|
||||||
|
|
||||||
N: Andrew Trick
|
|
||||||
E: atrick@apple.com
|
|
||||||
D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling
|
|
||||||
|
|
||||||
N: Ulrich Weigand
|
|
||||||
E: uweigand@de.ibm.com
|
|
||||||
D: SystemZ Backend
|
|
||||||
|
|
||||||
N: Bill Wendling
|
|
||||||
E: isanbard@gmail.com
|
|
||||||
D: libLTO, IR Linker
|
|
||||||
|
|
||||||
N: Peter Zotov
|
|
||||||
E: whitequark@whitequark.org
|
|
||||||
D: OCaml bindings
|
|
||||||
|
|
||||||
N: Andrey Churbanov
|
|
||||||
E: andrey.churbanov@intel.com
|
|
||||||
D: OpenMP runtime library
|
|
||||||
@@ -1,467 +0,0 @@
|
|||||||
This file is a partial list of people who have contributed to the LLVM
|
|
||||||
project. If you have contributed a patch or made some other contribution to
|
|
||||||
LLVM, please submit a patch to this file to add yourself, and it will be
|
|
||||||
done!
|
|
||||||
|
|
||||||
The list is sorted by surname and formatted to allow easy grepping and
|
|
||||||
beautification by scripts. The fields are: name (N), email (E), web-address
|
|
||||||
(W), PGP key ID and fingerprint (P), description (D), snail-mail address
|
|
||||||
(S), and (I) IRC handle.
|
|
||||||
|
|
||||||
|
|
||||||
N: Vikram Adve
|
|
||||||
E: vadve@cs.uiuc.edu
|
|
||||||
W: http://www.cs.uiuc.edu/~vadve/
|
|
||||||
D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM
|
|
||||||
|
|
||||||
N: Owen Anderson
|
|
||||||
E: resistor@mac.com
|
|
||||||
D: LCSSA pass and related LoopUnswitch work
|
|
||||||
D: GVNPRE pass, DataLayout refactoring, random improvements
|
|
||||||
|
|
||||||
N: Henrik Bach
|
|
||||||
D: MingW Win32 API portability layer
|
|
||||||
|
|
||||||
N: Aaron Ballman
|
|
||||||
E: aaron@aaronballman.com
|
|
||||||
D: __declspec attributes, Windows support, general bug fixing
|
|
||||||
|
|
||||||
N: Nate Begeman
|
|
||||||
E: natebegeman@mac.com
|
|
||||||
D: PowerPC backend developer
|
|
||||||
D: Target-independent code generator and analysis improvements
|
|
||||||
|
|
||||||
N: Daniel Berlin
|
|
||||||
E: dberlin@dberlin.org
|
|
||||||
D: ET-Forest implementation.
|
|
||||||
D: Sparse bitmap
|
|
||||||
|
|
||||||
N: David Blaikie
|
|
||||||
E: dblaikie@gmail.com
|
|
||||||
D: General bug fixing/fit & finish, mostly in Clang
|
|
||||||
|
|
||||||
N: Neil Booth
|
|
||||||
E: neil@daikokuya.co.uk
|
|
||||||
D: APFloat implementation.
|
|
||||||
|
|
||||||
N: Misha Brukman
|
|
||||||
E: brukman+llvm@uiuc.edu
|
|
||||||
W: http://misha.brukman.net
|
|
||||||
D: Portions of X86 and Sparc JIT compilers, PowerPC backend
|
|
||||||
D: Incremental bitcode loader
|
|
||||||
|
|
||||||
N: Cameron Buschardt
|
|
||||||
E: buschard@uiuc.edu
|
|
||||||
D: The `mem2reg' pass - promotes values stored in memory to registers
|
|
||||||
|
|
||||||
N: Brendon Cahoon
|
|
||||||
E: bcahoon@codeaurora.org
|
|
||||||
D: Loop unrolling with run-time trip counts.
|
|
||||||
|
|
||||||
N: Chandler Carruth
|
|
||||||
E: chandlerc@gmail.com
|
|
||||||
E: chandlerc@google.com
|
|
||||||
D: Hashing algorithms and interfaces
|
|
||||||
D: Inline cost analysis
|
|
||||||
D: Machine block placement pass
|
|
||||||
D: SROA
|
|
||||||
|
|
||||||
N: Casey Carter
|
|
||||||
E: ccarter@uiuc.edu
|
|
||||||
D: Fixes to the Reassociation pass, various improvement patches
|
|
||||||
|
|
||||||
N: Evan Cheng
|
|
||||||
E: evan.cheng@apple.com
|
|
||||||
D: ARM and X86 backends
|
|
||||||
D: Instruction scheduler improvements
|
|
||||||
D: Register allocator improvements
|
|
||||||
D: Loop optimizer improvements
|
|
||||||
D: Target-independent code generator improvements
|
|
||||||
|
|
||||||
N: Dan Villiom Podlaski Christiansen
|
|
||||||
E: danchr@gmail.com
|
|
||||||
E: danchr@cs.au.dk
|
|
||||||
W: http://villiom.dk
|
|
||||||
D: LLVM Makefile improvements
|
|
||||||
D: Clang diagnostic & driver tweaks
|
|
||||||
S: Aarhus, Denmark
|
|
||||||
|
|
||||||
N: Jeff Cohen
|
|
||||||
E: jeffc@jolt-lang.org
|
|
||||||
W: http://jolt-lang.org
|
|
||||||
D: Native Win32 API portability layer
|
|
||||||
|
|
||||||
N: John T. Criswell
|
|
||||||
E: criswell@uiuc.edu
|
|
||||||
D: Original Autoconf support, documentation improvements, bug fixes
|
|
||||||
|
|
||||||
N: Anshuman Dasgupta
|
|
||||||
E: adasgupt@codeaurora.org
|
|
||||||
D: Deterministic finite automaton based infrastructure for VLIW packetization
|
|
||||||
|
|
||||||
N: Stefanus Du Toit
|
|
||||||
E: stefanus.du.toit@intel.com
|
|
||||||
D: Bug fixes and minor improvements
|
|
||||||
|
|
||||||
N: Rafael Avila de Espindola
|
|
||||||
E: rafael.espindola@gmail.com
|
|
||||||
D: The ARM backend
|
|
||||||
|
|
||||||
N: Dave Estes
|
|
||||||
E: cestes@codeaurora.org
|
|
||||||
D: AArch64 machine description for Cortex-A53
|
|
||||||
|
|
||||||
N: Alkis Evlogimenos
|
|
||||||
E: alkis@evlogimenos.com
|
|
||||||
D: Linear scan register allocator, many codegen improvements, Java frontend
|
|
||||||
|
|
||||||
N: Hal Finkel
|
|
||||||
E: hfinkel@anl.gov
|
|
||||||
D: Basic-block autovectorization, PowerPC backend improvements
|
|
||||||
|
|
||||||
N: Eric Fiselier
|
|
||||||
E: eric@efcs.ca
|
|
||||||
D: LIT patches and documentation.
|
|
||||||
|
|
||||||
N: Ryan Flynn
|
|
||||||
E: pizza@parseerror.com
|
|
||||||
D: Miscellaneous bug fixes
|
|
||||||
|
|
||||||
N: Brian Gaeke
|
|
||||||
E: gaeke@uiuc.edu
|
|
||||||
W: http://www.students.uiuc.edu/~gaeke/
|
|
||||||
D: Portions of X86 static and JIT compilers; initial SparcV8 backend
|
|
||||||
D: Dynamic trace optimizer
|
|
||||||
D: FreeBSD/X86 compatibility fixes, the llvm-nm tool
|
|
||||||
|
|
||||||
N: Nicolas Geoffray
|
|
||||||
E: nicolas.geoffray@lip6.fr
|
|
||||||
W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/
|
|
||||||
D: PPC backend fixes for Linux
|
|
||||||
|
|
||||||
N: Louis Gerbarg
|
|
||||||
E: lgg@apple.com
|
|
||||||
D: Portions of the PowerPC backend
|
|
||||||
|
|
||||||
N: Saem Ghani
|
|
||||||
E: saemghani@gmail.com
|
|
||||||
D: Callgraph class cleanups
|
|
||||||
|
|
||||||
N: Mikhail Glushenkov
|
|
||||||
E: foldr@codedgers.com
|
|
||||||
D: Author of llvmc2
|
|
||||||
|
|
||||||
N: Dan Gohman
|
|
||||||
E: sunfish@mozilla.com
|
|
||||||
D: Miscellaneous bug fixes
|
|
||||||
D: WebAssembly Backend
|
|
||||||
|
|
||||||
N: David Goodwin
|
|
||||||
E: david@goodwinz.net
|
|
||||||
D: Thumb-2 code generator
|
|
||||||
|
|
||||||
N: David Greene
|
|
||||||
E: greened@obbligato.org
|
|
||||||
D: Miscellaneous bug fixes
|
|
||||||
D: Register allocation refactoring
|
|
||||||
|
|
||||||
N: Gabor Greif
|
|
||||||
E: ggreif@gmail.com
|
|
||||||
D: Improvements for space efficiency
|
|
||||||
|
|
||||||
N: James Grosbach
|
|
||||||
E: grosbach@apple.com
|
|
||||||
I: grosbach
|
|
||||||
D: SjLj exception handling support
|
|
||||||
D: General fixes and improvements for the ARM back-end
|
|
||||||
D: MCJIT
|
|
||||||
D: ARM integrated assembler and assembly parser
|
|
||||||
D: Led effort for the backend formerly known as ARM64
|
|
||||||
|
|
||||||
N: Lang Hames
|
|
||||||
E: lhames@gmail.com
|
|
||||||
D: PBQP-based register allocator
|
|
||||||
|
|
||||||
N: Gordon Henriksen
|
|
||||||
E: gordonhenriksen@mac.com
|
|
||||||
D: Pluggable GC support
|
|
||||||
D: C interface
|
|
||||||
D: Ocaml bindings
|
|
||||||
|
|
||||||
N: Raul Fernandes Herbster
|
|
||||||
E: raul@dsc.ufcg.edu.br
|
|
||||||
D: JIT support for ARM
|
|
||||||
|
|
||||||
N: Paolo Invernizzi
|
|
||||||
E: arathorn@fastwebnet.it
|
|
||||||
D: Visual C++ compatibility fixes
|
|
||||||
|
|
||||||
N: Patrick Jenkins
|
|
||||||
E: patjenk@wam.umd.edu
|
|
||||||
D: Nightly Tester
|
|
||||||
|
|
||||||
N: Dale Johannesen
|
|
||||||
E: dalej@apple.com
|
|
||||||
D: ARM constant islands improvements
|
|
||||||
D: Tail merging improvements
|
|
||||||
D: Rewrite X87 back end
|
|
||||||
D: Use APFloat for floating point constants widely throughout compiler
|
|
||||||
D: Implement X87 long double
|
|
||||||
|
|
||||||
N: Brad Jones
|
|
||||||
E: kungfoomaster@nondot.org
|
|
||||||
D: Support for packed types
|
|
||||||
|
|
||||||
N: Rod Kay
|
|
||||||
E: rkay@auroraux.org
|
|
||||||
D: Author of LLVM Ada bindings
|
|
||||||
|
|
||||||
N: Eric Kidd
|
|
||||||
W: http://randomhacks.net/
|
|
||||||
D: llvm-config script
|
|
||||||
|
|
||||||
N: Anton Korobeynikov
|
|
||||||
E: asl@math.spbu.ru
|
|
||||||
D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv.
|
|
||||||
D: x86/linux PIC codegen, aliases, regparm/visibility attributes
|
|
||||||
D: Switch lowering refactoring
|
|
||||||
|
|
||||||
N: Sumant Kowshik
|
|
||||||
E: kowshik@uiuc.edu
|
|
||||||
D: Author of the original C backend
|
|
||||||
|
|
||||||
N: Benjamin Kramer
|
|
||||||
E: benny.kra@gmail.com
|
|
||||||
D: Miscellaneous bug fixes
|
|
||||||
|
|
||||||
N: Sundeep Kushwaha
|
|
||||||
E: sundeepk@codeaurora.org
|
|
||||||
D: Implemented DFA-based target independent VLIW packetizer
|
|
||||||
|
|
||||||
N: Christopher Lamb
|
|
||||||
E: christopher.lamb@gmail.com
|
|
||||||
D: aligned load/store support, parts of noalias and restrict support
|
|
||||||
D: vreg subreg infrastructure, X86 codegen improvements based on subregs
|
|
||||||
D: address spaces
|
|
||||||
|
|
||||||
N: Jim Laskey
|
|
||||||
E: jlaskey@apple.com
|
|
||||||
D: Improvements to the PPC backend, instruction scheduling
|
|
||||||
D: Debug and Dwarf implementation
|
|
||||||
D: Auto upgrade mangler
|
|
||||||
D: llvm-gcc4 svn wrangler
|
|
||||||
|
|
||||||
N: Chris Lattner
|
|
||||||
E: sabre@nondot.org
|
|
||||||
W: http://nondot.org/~sabre/
|
|
||||||
D: Primary architect of LLVM
|
|
||||||
|
|
||||||
N: Tanya Lattner (Tanya Brethour)
|
|
||||||
E: tonic@nondot.org
|
|
||||||
W: http://nondot.org/~tonic/
|
|
||||||
D: The initial llvm-ar tool, converted regression testsuite to dejagnu
|
|
||||||
D: Modulo scheduling in the SparcV9 backend
|
|
||||||
D: Release manager (1.7+)
|
|
||||||
|
|
||||||
N: Sylvestre Ledru
|
|
||||||
E: sylvestre@debian.org
|
|
||||||
W: http://sylvestre.ledru.info/
|
|
||||||
W: http://llvm.org/apt/
|
|
||||||
D: Debian and Ubuntu packaging
|
|
||||||
D: Continuous integration with jenkins
|
|
||||||
|
|
||||||
N: Andrew Lenharth
|
|
||||||
E: alenhar2@cs.uiuc.edu
|
|
||||||
W: http://www.lenharth.org/~andrewl/
|
|
||||||
D: Alpha backend
|
|
||||||
D: Sampling based profiling
|
|
||||||
|
|
||||||
N: Nick Lewycky
|
|
||||||
E: nicholas@mxc.ca
|
|
||||||
D: PredicateSimplifier pass
|
|
||||||
|
|
||||||
N: Tony Linthicum, et. al.
|
|
||||||
E: tlinth@codeaurora.org
|
|
||||||
D: Backend for Qualcomm's Hexagon VLIW processor.
|
|
||||||
|
|
||||||
N: Bruno Cardoso Lopes
|
|
||||||
E: bruno.cardoso@gmail.com
|
|
||||||
I: bruno
|
|
||||||
W: http://brunocardoso.cc
|
|
||||||
D: Mips backend
|
|
||||||
D: Random ARM integrated assembler and assembly parser improvements
|
|
||||||
D: General X86 AVX1 support
|
|
||||||
|
|
||||||
N: Duraid Madina
|
|
||||||
E: duraid@octopus.com.au
|
|
||||||
W: http://kinoko.c.u-tokyo.ac.jp/~duraid/
|
|
||||||
D: IA64 backend, BigBlock register allocator
|
|
||||||
|
|
||||||
N: John McCall
|
|
||||||
E: rjmccall@apple.com
|
|
||||||
D: Clang semantic analysis and IR generation
|
|
||||||
|
|
||||||
N: Michael McCracken
|
|
||||||
E: michael.mccracken@gmail.com
|
|
||||||
D: Line number support for llvmgcc
|
|
||||||
|
|
||||||
N: Vladimir Merzliakov
|
|
||||||
E: wanderer@rsu.ru
|
|
||||||
D: Test suite fixes for FreeBSD
|
|
||||||
|
|
||||||
N: Scott Michel
|
|
||||||
E: scottm@aero.org
|
|
||||||
D: Added STI Cell SPU backend.
|
|
||||||
|
|
||||||
N: Kai Nacke
|
|
||||||
E: kai@redstar.de
|
|
||||||
D: Support for implicit TLS model used with MS VC runtime
|
|
||||||
D: Dumping of Win64 EH structures
|
|
||||||
|
|
||||||
N: Takumi Nakamura
|
|
||||||
E: geek4civic@gmail.com
|
|
||||||
E: chapuni@hf.rim.or.jp
|
|
||||||
D: Cygwin and MinGW support.
|
|
||||||
D: Win32 tweaks.
|
|
||||||
S: Yokohama, Japan
|
|
||||||
|
|
||||||
N: Edward O'Callaghan
|
|
||||||
E: eocallaghan@auroraux.org
|
|
||||||
W: http://www.auroraux.org
|
|
||||||
D: Add Clang support with various other improvements to utils/NewNightlyTest.pl
|
|
||||||
D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings
|
|
||||||
D: and error clean ups.
|
|
||||||
|
|
||||||
N: Morten Ofstad
|
|
||||||
E: morten@hue.no
|
|
||||||
D: Visual C++ compatibility fixes
|
|
||||||
|
|
||||||
N: Jakob Stoklund Olesen
|
|
||||||
E: stoklund@2pi.dk
|
|
||||||
D: Machine code verifier
|
|
||||||
D: Blackfin backend
|
|
||||||
D: Fast register allocator
|
|
||||||
D: Greedy register allocator
|
|
||||||
|
|
||||||
N: Richard Osborne
|
|
||||||
E: richard@xmos.com
|
|
||||||
D: XCore backend
|
|
||||||
|
|
||||||
N: Devang Patel
|
|
||||||
E: dpatel@apple.com
|
|
||||||
D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate
|
|
||||||
D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements
|
|
||||||
D: Optimizer improvements, Loop Index Split
|
|
||||||
|
|
||||||
N: Ana Pazos
|
|
||||||
E: apazos@codeaurora.org
|
|
||||||
D: Fixes and improvements to the AArch64 backend
|
|
||||||
|
|
||||||
N: Wesley Peck
|
|
||||||
E: peckw@wesleypeck.com
|
|
||||||
W: http://wesleypeck.com/
|
|
||||||
D: MicroBlaze backend
|
|
||||||
|
|
||||||
N: Francois Pichet
|
|
||||||
E: pichet2000@gmail.com
|
|
||||||
D: MSVC support
|
|
||||||
|
|
||||||
N: Vladimir Prus
|
|
||||||
W: http://vladimir_prus.blogspot.com
|
|
||||||
E: ghost@cs.msu.su
|
|
||||||
D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass
|
|
||||||
|
|
||||||
N: Kalle Raiskila
|
|
||||||
E: kalle.rasikila@nokia.com
|
|
||||||
D: Some bugfixes to CellSPU
|
|
||||||
|
|
||||||
N: Xerxes Ranby
|
|
||||||
E: xerxes@zafena.se
|
|
||||||
D: Cmake dependency chain and various bug fixes
|
|
||||||
|
|
||||||
N: Alex Rosenberg
|
|
||||||
E: alexr@leftfield.org
|
|
||||||
I: arosenberg
|
|
||||||
D: ARM calling conventions rewrite, hard float support
|
|
||||||
|
|
||||||
N: Chad Rosier
|
|
||||||
E: mcrosier@codeaurora.org
|
|
||||||
I: mcrosier
|
|
||||||
D: AArch64 fast instruction selection pass
|
|
||||||
D: Fixes and improvements to the ARM fast-isel pass
|
|
||||||
D: Fixes and improvements to the AArch64 backend
|
|
||||||
|
|
||||||
N: Nadav Rotem
|
|
||||||
E: nrotem@apple.com
|
|
||||||
D: X86 code generation improvements, Loop Vectorizer.
|
|
||||||
|
|
||||||
N: Roman Samoilov
|
|
||||||
E: roman@codedgers.com
|
|
||||||
D: MSIL backend
|
|
||||||
|
|
||||||
N: Duncan Sands
|
|
||||||
E: baldrick@free.fr
|
|
||||||
I: baldrick
|
|
||||||
D: Ada support in llvm-gcc
|
|
||||||
D: Dragonegg plugin
|
|
||||||
D: Exception handling improvements
|
|
||||||
D: Type legalizer rewrite
|
|
||||||
|
|
||||||
N: Ruchira Sasanka
|
|
||||||
E: sasanka@uiuc.edu
|
|
||||||
D: Graph coloring register allocator for the Sparc64 backend
|
|
||||||
|
|
||||||
N: Arnold Schwaighofer
|
|
||||||
E: arnold.schwaighofer@gmail.com
|
|
||||||
D: Tail call optimization for the x86 backend
|
|
||||||
|
|
||||||
N: Shantonu Sen
|
|
||||||
E: ssen@apple.com
|
|
||||||
D: Miscellaneous bug fixes
|
|
||||||
|
|
||||||
N: Anand Shukla
|
|
||||||
E: ashukla@cs.uiuc.edu
|
|
||||||
D: The `paths' pass
|
|
||||||
|
|
||||||
N: Michael J. Spencer
|
|
||||||
E: bigcheesegs@gmail.com
|
|
||||||
D: Shepherding Windows COFF support into MC.
|
|
||||||
D: Lots of Windows stuff.
|
|
||||||
|
|
||||||
N: Reid Spencer
|
|
||||||
E: rspencer@reidspencer.com
|
|
||||||
W: http://reidspencer.com/
|
|
||||||
D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid
|
|
||||||
|
|
||||||
N: Alp Toker
|
|
||||||
E: alp@nuanti.com
|
|
||||||
W: http://atoker.com/
|
|
||||||
D: C++ frontend next generation standards implementation
|
|
||||||
|
|
||||||
N: Craig Topper
|
|
||||||
E: craig.topper@gmail.com
|
|
||||||
D: X86 codegen and disassembler improvements. AVX2 support.
|
|
||||||
|
|
||||||
N: Edwin Torok
|
|
||||||
E: edwintorok@gmail.com
|
|
||||||
D: Miscellaneous bug fixes
|
|
||||||
|
|
||||||
N: Adam Treat
|
|
||||||
E: manyoso@yahoo.com
|
|
||||||
D: C++ bugs filed, and C++ front-end bug fixes.
|
|
||||||
|
|
||||||
N: Lauro Ramos Venancio
|
|
||||||
E: lauro.venancio@indt.org.br
|
|
||||||
D: ARM backend improvements
|
|
||||||
D: Thread Local Storage implementation
|
|
||||||
|
|
||||||
N: Bill Wendling
|
|
||||||
I: wendling
|
|
||||||
E: isanbard@gmail.com
|
|
||||||
D: Release manager, IR Linker, LTO
|
|
||||||
D: Bunches of stuff
|
|
||||||
|
|
||||||
N: Bob Wilson
|
|
||||||
E: bob.wilson@acm.org
|
|
||||||
D: Advanced SIMD (NEON) support in the ARM backend.
|
|
||||||
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
==============================================================================
|
|
||||||
LLVM Release License
|
|
||||||
==============================================================================
|
|
||||||
University of Illinois/NCSA
|
|
||||||
Open Source License
|
|
||||||
|
|
||||||
Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Developed by:
|
|
||||||
|
|
||||||
LLVM Team
|
|
||||||
|
|
||||||
University of Illinois at Urbana-Champaign
|
|
||||||
|
|
||||||
http://llvm.org
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal with
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimers.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimers in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the names of the LLVM Team, University of Illinois at
|
|
||||||
Urbana-Champaign, nor the names of its contributors may be used to
|
|
||||||
endorse or promote products derived from this Software without specific
|
|
||||||
prior written permission.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Copyrights and Licenses for Third Party Software Distributed with LLVM:
|
|
||||||
==============================================================================
|
|
||||||
The LLVM software contains code written by third parties. Such software will
|
|
||||||
have its own individual LICENSE.TXT file in the directory in which it appears.
|
|
||||||
This file will describe the copyrights, license, and restrictions which apply
|
|
||||||
to that code.
|
|
||||||
|
|
||||||
The disclaimer of warranty in the University of Illinois Open Source License
|
|
||||||
applies to all code in the LLVM Distribution, and nothing in any of the
|
|
||||||
other licenses gives permission to use the names of the LLVM Team or the
|
|
||||||
University of Illinois to endorse or promote products derived from this
|
|
||||||
Software.
|
|
||||||
|
|
||||||
The following pieces of software have additional or alternate copyrights,
|
|
||||||
licenses, and/or restrictions:
|
|
||||||
|
|
||||||
Program Directory
|
|
||||||
------- ---------
|
|
||||||
Autoconf llvm/autoconf
|
|
||||||
llvm/projects/ModuleMaker/autoconf
|
|
||||||
Google Test llvm/utils/unittest/googletest
|
|
||||||
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
|
|
||||||
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
|
|
||||||
ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
|
|
||||||
md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
|
|
||||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -1,8 +1,8 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
||||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
|
|
||||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
||||||
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
|
||||||
set _NO_DEBUG_HEAP=1
|
set _NO_DEBUG_HEAP=1
|
||||||
|
|
||||||
set path=w:\Odin\misc;%path%
|
set path=w:\Odin\misc;%path%
|
||||||
|
|||||||
+17
-3
@@ -33,6 +33,10 @@ struct Operand {
|
|||||||
BuiltinProcId builtin_id;
|
BuiltinProcId builtin_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
b32 is_operand_nil(Operand *o) {
|
||||||
|
return o->mode == Addressing_Value && o->type == t_untyped_nil;
|
||||||
|
}
|
||||||
|
|
||||||
struct TypeAndValue {
|
struct TypeAndValue {
|
||||||
AddressingMode mode;
|
AddressingMode mode;
|
||||||
Type *type;
|
Type *type;
|
||||||
@@ -241,7 +245,9 @@ struct Checker {
|
|||||||
gbArray(ProcedureInfo) procs; // NOTE(bill): Procedures to check
|
gbArray(ProcedureInfo) procs; // NOTE(bill): Procedures to check
|
||||||
|
|
||||||
gbArena arena;
|
gbArena arena;
|
||||||
|
gbArena tmp_arena;
|
||||||
gbAllocator allocator;
|
gbAllocator allocator;
|
||||||
|
gbAllocator tmp_allocator;
|
||||||
|
|
||||||
CheckerContext context;
|
CheckerContext context;
|
||||||
|
|
||||||
@@ -501,9 +507,10 @@ void init_universal_scope(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
add_global_constant(a, make_string("true"), t_untyped_bool, make_exact_value_bool(true));
|
add_global_constant(a, make_string("true"), t_untyped_bool, make_exact_value_bool(true));
|
||||||
add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false));
|
add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false));
|
||||||
add_global_constant(a, make_string("null"), t_untyped_pointer, make_exact_value_pointer(NULL));
|
|
||||||
|
add_global_entity(make_entity_nil(a, NULL, make_token_ident(make_string("nil")), t_untyped_nil));
|
||||||
|
|
||||||
// Builtin Procedures
|
// Builtin Procedures
|
||||||
for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
|
for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
|
||||||
@@ -564,7 +571,10 @@ void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) {
|
|||||||
}
|
}
|
||||||
isize arena_size = 2 * item_size * total_token_count;
|
isize arena_size = 2 * item_size * total_token_count;
|
||||||
gb_arena_init_from_allocator(&c->arena, a, arena_size);
|
gb_arena_init_from_allocator(&c->arena, a, arena_size);
|
||||||
|
gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size);
|
||||||
|
|
||||||
c->allocator = gb_arena_allocator(&c->arena);
|
c->allocator = gb_arena_allocator(&c->arena);
|
||||||
|
c->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
|
||||||
|
|
||||||
c->global_scope = make_scope(universal_scope, c->allocator);
|
c->global_scope = make_scope(universal_scope, c->allocator);
|
||||||
c->context.scope = c->global_scope;
|
c->context.scope = c->global_scope;
|
||||||
@@ -705,6 +715,10 @@ void add_type_info_type(Checker *c, Type *t) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t = default_type(t);
|
t = default_type(t);
|
||||||
|
if (is_type_untyped(t)) {
|
||||||
|
return; // Could be nil
|
||||||
|
}
|
||||||
|
|
||||||
if (map_get(&c->info.type_info_map, hash_pointer(t)) != NULL) {
|
if (map_get(&c->info.type_info_map, hash_pointer(t)) != NULL) {
|
||||||
// Types have already been added
|
// Types have already been added
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ enum BuiltinProcId;
|
|||||||
ENTITY_KIND(Procedure), \
|
ENTITY_KIND(Procedure), \
|
||||||
ENTITY_KIND(Builtin), \
|
ENTITY_KIND(Builtin), \
|
||||||
ENTITY_KIND(ImportName), \
|
ENTITY_KIND(ImportName), \
|
||||||
|
ENTITY_KIND(Nil), \
|
||||||
ENTITY_KIND(Count),
|
ENTITY_KIND(Count),
|
||||||
|
|
||||||
|
|
||||||
@@ -68,6 +69,8 @@ struct Entity {
|
|||||||
Scope *scope;
|
Scope *scope;
|
||||||
b32 used;
|
b32 used;
|
||||||
} ImportName;
|
} ImportName;
|
||||||
|
struct {
|
||||||
|
} Nil;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,6 +158,12 @@ Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity *make_entity_nil(gbAllocator a, Scope *scope, Token token, Type *type) {
|
||||||
|
Entity *entity = alloc_entity(a, Entity_Nil, scope, token, type);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) {
|
Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) {
|
||||||
token.string = make_string("_");
|
token.string = make_string("_");
|
||||||
return make_entity_variable(a, file_scope, token, NULL);
|
return make_entity_variable(a, file_scope, token, NULL);
|
||||||
|
|||||||
+139
-84
@@ -68,13 +68,16 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
|||||||
if (is_type_untyped(src)) {
|
if (is_type_untyped(src)) {
|
||||||
switch (dst->kind) {
|
switch (dst->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
if (operand->mode == Addressing_Constant)
|
if (operand->mode == Addressing_Constant) {
|
||||||
return check_value_is_expressible(c, operand->value, dst, NULL);
|
return check_value_is_expressible(c, operand->value, dst, NULL);
|
||||||
if (src->kind == Type_Basic)
|
}
|
||||||
return src->Basic.kind == Basic_UntypedBool && is_type_boolean(dst);
|
if (src->kind == Type_Basic && src->Basic.kind == Basic_UntypedBool) {
|
||||||
|
return is_type_boolean(dst);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Type_Pointer:
|
}
|
||||||
return src->Basic.kind == Basic_UntypedPointer;
|
if (type_has_nil(dst)) {
|
||||||
|
return is_operand_nil(operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +88,10 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_untyped_nil(src)) {
|
||||||
|
return type_has_nil(dst);
|
||||||
|
}
|
||||||
|
|
||||||
// ^T <- rawptr
|
// ^T <- rawptr
|
||||||
// TODO(bill): Should C-style (not C++) pointer cast be allowed?
|
// TODO(bill): Should C-style (not C++) pointer cast be allowed?
|
||||||
// if (is_type_pointer(dst) && is_type_rawptr(src)) {
|
// if (is_type_pointer(dst) && is_type_rawptr(src)) {
|
||||||
@@ -146,7 +153,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
|
|||||||
if (is_type_untyped(operand->type)) {
|
if (is_type_untyped(operand->type)) {
|
||||||
Type *target_type = type;
|
Type *target_type = type;
|
||||||
|
|
||||||
if (type == NULL || is_type_any(type)) {
|
if (type == NULL || is_type_any(type) || is_type_untyped_nil(type)) {
|
||||||
|
if (type == NULL && base_type(operand->type) == t_untyped_nil) {
|
||||||
|
error(ast_node_token(operand->expr), "Use of untyped nil in %.*s", LIT(context_name));
|
||||||
|
operand->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
add_type_info_type(c, type);
|
add_type_info_type(c, type);
|
||||||
target_type = default_type(operand->type);
|
target_type = default_type(operand->type);
|
||||||
}
|
}
|
||||||
@@ -229,14 +242,15 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
isize other_field_index = 0;
|
isize other_field_index = 0;
|
||||||
Entity *using_index_expr = NULL;
|
Entity *using_index_expr = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
struct Delay {
|
struct Delay {
|
||||||
Entity *e;
|
Entity *e;
|
||||||
AstNode *t;
|
AstNode *t;
|
||||||
};
|
};
|
||||||
gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
|
gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, other_field_count);
|
||||||
gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator());
|
gbArray(Delay) delayed_type; gb_array_init_reserve(delayed_type, c->tmp_allocator, other_field_count);
|
||||||
defer (gb_array_free(delayed_const));
|
|
||||||
defer (gb_array_free(delayed_type));
|
|
||||||
|
|
||||||
gb_for_array(decl_index, decls) {
|
gb_for_array(decl_index, decls) {
|
||||||
AstNode *decl = decls[decl_index];
|
AstNode *decl = decls[decl_index];
|
||||||
@@ -729,8 +743,8 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
make_token_ident(make_string("max_value")), constant_type, make_exact_value_integer(max_value));
|
make_token_ident(make_string("max_value")), constant_type, make_exact_value_integer(max_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_variadic_) {
|
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) {
|
||||||
if (fields == NULL || gb_array_count(fields) == 0)
|
if (params == NULL || gb_array_count(params) == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
b32 is_variadic = false;
|
b32 is_variadic = false;
|
||||||
@@ -738,33 +752,32 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_va
|
|||||||
Type *tuple = make_type_tuple(c->allocator);
|
Type *tuple = make_type_tuple(c->allocator);
|
||||||
|
|
||||||
isize variable_count = 0;
|
isize variable_count = 0;
|
||||||
gb_for_array(i, fields) {
|
gb_for_array(i, params) {
|
||||||
AstNode *field = fields[i];
|
AstNode *field = params[i];
|
||||||
ast_node(f, Field, field);
|
ast_node(p, Parameter, field);
|
||||||
variable_count += gb_array_count(f->names);
|
variable_count += gb_array_count(p->names);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
|
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
|
||||||
isize variable_index = 0;
|
isize variable_index = 0;
|
||||||
gb_for_array(i, fields) {
|
gb_for_array(i, params) {
|
||||||
AstNode *field = fields[i];
|
ast_node(p, Parameter, params[i]);
|
||||||
ast_node(f, Field, field);
|
AstNode *type_expr = p->type;
|
||||||
AstNode *type_expr = f->type;
|
|
||||||
if (type_expr) {
|
if (type_expr) {
|
||||||
if (type_expr->kind == AstNode_Ellipsis) {
|
if (type_expr->kind == AstNode_Ellipsis) {
|
||||||
type_expr = type_expr->Ellipsis.expr;
|
type_expr = type_expr->Ellipsis.expr;
|
||||||
if (i+1 == gb_array_count(fields)) {
|
if (i+1 == gb_array_count(params)) {
|
||||||
is_variadic = true;
|
is_variadic = true;
|
||||||
} else {
|
} else {
|
||||||
error(ast_node_token(field), "Invalid AST: Invalid variadic parameter");
|
error(ast_node_token(params[i]), "Invalid AST: Invalid variadic parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *type = check_type(c, type_expr);
|
Type *type = check_type(c, type_expr);
|
||||||
gb_for_array(j, f->names) {
|
gb_for_array(j, p->names) {
|
||||||
AstNode *name = f->names[j];
|
AstNode *name = p->names[j];
|
||||||
if (name->kind == AstNode_Ident) {
|
if (name->kind == AstNode_Ident) {
|
||||||
Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, f->is_using);
|
Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, p->is_using);
|
||||||
add_entity(c, scope, name, param);
|
add_entity(c, scope, name, param);
|
||||||
variables[variable_index++] = param;
|
variables[variable_index++] = param;
|
||||||
} else {
|
} else {
|
||||||
@@ -774,10 +787,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_va
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_variadic && gb_array_count(fields) > 0) {
|
if (is_variadic && gb_array_count(params) > 0) {
|
||||||
// NOTE(bill): Change last variadic parameter to be a slice
|
// NOTE(bill): Change last variadic parameter to be a slice
|
||||||
// Custom Calling convention for variadic parameters
|
// Custom Calling convention for variadic parameters
|
||||||
Entity *end = variables[gb_array_count(fields)-1];
|
Entity *end = variables[gb_array_count(params)-1];
|
||||||
end->type = make_type_slice(c->allocator, end->type);
|
end->type = make_type_slice(c->allocator, end->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -927,6 +940,10 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
|||||||
error(ast_node_token(n), "Use of import `%.*s` not in selector", LIT(e->ImportName.name));
|
error(ast_node_token(n), "Use of import `%.*s` not in selector", LIT(e->ImportName.name));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case Entity_Nil:
|
||||||
|
o->mode = Addressing_Value;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
compiler_error("Compiler error: Unknown EntityKind");
|
compiler_error("Compiler error: Unknown EntityKind");
|
||||||
break;
|
break;
|
||||||
@@ -1184,15 +1201,20 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token_Mod:
|
|
||||||
case Token_And:
|
case Token_And:
|
||||||
case Token_Or:
|
case Token_Or:
|
||||||
case Token_Xor:
|
|
||||||
case Token_AndNot:
|
|
||||||
|
|
||||||
case Token_ModEq:
|
|
||||||
case Token_AndEq:
|
case Token_AndEq:
|
||||||
case Token_OrEq:
|
case Token_OrEq:
|
||||||
|
if (!is_type_integer(type) && !is_type_boolean(type)) {
|
||||||
|
error(op, "Operator `%.*s` is only allowed with integers or booleans", LIT(op.string));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Token_Mod:
|
||||||
|
case Token_Xor:
|
||||||
|
case Token_AndNot:
|
||||||
|
case Token_ModEq:
|
||||||
case Token_XorEq:
|
case Token_XorEq:
|
||||||
case Token_AndNotEq:
|
case Token_AndNotEq:
|
||||||
if (!is_type_integer(type)) {
|
if (!is_type_integer(type)) {
|
||||||
@@ -1350,7 +1372,17 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
|||||||
|
|
||||||
if (o->mode == Addressing_Constant) {
|
if (o->mode == Addressing_Constant) {
|
||||||
Type *type = base_type(o->type);
|
Type *type = base_type(o->type);
|
||||||
GB_ASSERT(type->kind == Type_Basic);
|
if (type->kind != Type_Basic) {
|
||||||
|
gbString xt = type_to_string(o->type);
|
||||||
|
gbString err_str = expr_to_string(node);
|
||||||
|
defer (gb_string_free(xt));
|
||||||
|
defer (gb_string_free(err_str));
|
||||||
|
error(op, "Invalid type, `%s`, for constant unary expression `%s`", xt, err_str);
|
||||||
|
o->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
i32 precision = 0;
|
i32 precision = 0;
|
||||||
if (is_type_unsigned(type))
|
if (is_type_unsigned(type))
|
||||||
precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
|
precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type));
|
||||||
@@ -1368,6 +1400,9 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
gbString err_str = NULL;
|
gbString err_str = NULL;
|
||||||
defer ({
|
defer ({
|
||||||
if (err_str != NULL)
|
if (err_str != NULL)
|
||||||
@@ -1392,16 +1427,16 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
|||||||
|
|
||||||
if (!defined) {
|
if (!defined) {
|
||||||
gbString type_string = type_to_string(x->type);
|
gbString type_string = type_to_string(x->type);
|
||||||
err_str = gb_string_make(gb_heap_allocator(),
|
defer (gb_string_free(type_string));
|
||||||
|
err_str = gb_string_make(c->tmp_allocator,
|
||||||
gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(op.string), type_string));
|
gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(op.string), type_string));
|
||||||
gb_string_free(type_string);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gbString xt = type_to_string(x->type);
|
gbString xt = type_to_string(x->type);
|
||||||
gbString yt = type_to_string(y->type);
|
gbString yt = type_to_string(y->type);
|
||||||
defer(gb_string_free(xt));
|
defer(gb_string_free(xt));
|
||||||
defer(gb_string_free(yt));
|
defer(gb_string_free(yt));
|
||||||
err_str = gb_string_make(gb_heap_allocator(),
|
err_str = gb_string_make(c->tmp_allocator,
|
||||||
gb_bprintf("mismatched types `%s` and `%s`", xt, yt));
|
gb_bprintf("mismatched types `%s` and `%s`", xt, yt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1853,7 +1888,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
|||||||
ExactValue b = y->value;
|
ExactValue b = y->value;
|
||||||
|
|
||||||
Type *type = base_type(x->type);
|
Type *type = base_type(x->type);
|
||||||
GB_ASSERT(type->kind == Type_Basic);
|
if (type->kind != Type_Basic) {
|
||||||
|
gbString xt = type_to_string(x->type);
|
||||||
|
defer (gb_string_free(xt));
|
||||||
|
err_str = expr_to_string(node);
|
||||||
|
error(op, "Invalid type, `%s`, for constant binary expression `%s`", xt, err_str);
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (op.kind == Token_Quo && is_type_integer(type)) {
|
if (op.kind == Token_Quo && is_type_integer(type)) {
|
||||||
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
|
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
|
||||||
}
|
}
|
||||||
@@ -1932,8 +1975,10 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
|
|
||||||
if (operand->mode == Addressing_Constant) {
|
if (operand->mode == Addressing_Constant) {
|
||||||
if (operand->value.value_integer == 0) {
|
if (operand->value.value_integer == 0) {
|
||||||
// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
|
if (make_string(expr_str) != "nil") { // HACK NOTE(bill): Just in case
|
||||||
extra_text = " - Did you want `null`?";
|
// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
|
||||||
|
extra_text = " - Did you want `nil`?";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error(ast_node_token(operand->expr), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text);
|
error(ast_node_token(operand->expr), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text);
|
||||||
@@ -1989,36 +2034,27 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Type_Pointer:
|
|
||||||
switch (operand->type->Basic.kind) {
|
|
||||||
case Basic_UntypedPointer:
|
|
||||||
target_type = t_untyped_pointer;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
convert_untyped_error(c, operand, target_type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type_Proc:
|
case Basic_UntypedNil:
|
||||||
switch (operand->type->Basic.kind) {
|
if (!type_has_nil(target_type)) {
|
||||||
case Basic_UntypedPointer:
|
convert_untyped_error(c, operand, target_type);
|
||||||
break;
|
return;
|
||||||
default:
|
}
|
||||||
convert_untyped_error(c, operand, target_type);
|
break;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
convert_untyped_error(c, operand, target_type);
|
if (!type_has_nil(target_type)) {
|
||||||
return;
|
convert_untyped_error(c, operand, target_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
operand->type = target_type;
|
operand->type = target_type;
|
||||||
|
update_expr_type(c, operand->expr, target_type, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
|
b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
|
||||||
@@ -2415,6 +2451,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
error(ast_node_token(expr), "Invalid argument to `type_info`");
|
error(ast_node_token(expr), "Invalid argument to `type_info`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_type_info_type(c, type);
|
add_type_info_type(c, type);
|
||||||
|
|
||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
@@ -2993,10 +3030,12 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
isize operand_count = 0;
|
isize operand_count = 0;
|
||||||
gbArray(Operand) operands;
|
gbArray(Operand) operands;
|
||||||
gb_array_init_reserve(operands, gb_heap_allocator(), 2*param_count);
|
gb_array_init_reserve(operands, c->tmp_allocator, 2*param_count);
|
||||||
defer (gb_array_free(operands));
|
|
||||||
|
|
||||||
gb_for_array(i, ce->args) {
|
gb_for_array(i, ce->args) {
|
||||||
Operand o = {};
|
Operand o = {};
|
||||||
@@ -3374,12 +3413,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
error(ast_node_token(e), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count);
|
error(ast_node_token(e), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand o = {};
|
Operand operand = {};
|
||||||
check_expr_with_type_hint(c, &o, e, elem_type);
|
check_expr_with_type_hint(c, &operand, e, elem_type);
|
||||||
check_assignment(c, &o, elem_type, context_name);
|
check_assignment(c, &operand, elem_type, context_name);
|
||||||
|
|
||||||
if (is_constant) {
|
if (is_constant) {
|
||||||
is_constant = o.mode == Addressing_Constant;
|
is_constant = operand.mode == Addressing_Constant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max < index)
|
if (max < index)
|
||||||
@@ -3730,10 +3769,9 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) {
|
|||||||
check_expr_base(c, o, e);
|
check_expr_base(c, o, e);
|
||||||
check_not_tuple(c, o);
|
check_not_tuple(c, o);
|
||||||
if (o->mode == Addressing_NoValue) {
|
if (o->mode == Addressing_NoValue) {
|
||||||
AstNode *e = o->expr;
|
gbString str = expr_to_string(o->expr);
|
||||||
gbString str = expr_to_string(e);
|
|
||||||
defer (gb_string_free(str));
|
defer (gb_string_free(str));
|
||||||
error(ast_node_token(e),
|
error(ast_node_token(o->expr),
|
||||||
"`%s` used as value or type", str);
|
"`%s` used as value or type", str);
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
}
|
}
|
||||||
@@ -3742,15 +3780,14 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) {
|
|||||||
|
|
||||||
gbString write_expr_to_string(gbString str, AstNode *node);
|
gbString write_expr_to_string(gbString str, AstNode *node);
|
||||||
|
|
||||||
gbString write_fields_to_string(gbString str, AstNodeArray fields, char *sep) {
|
gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
|
||||||
gb_for_array(i, fields) {
|
gb_for_array(i, params) {
|
||||||
AstNode *field = fields[i];
|
ast_node(p, Parameter, params[i]);
|
||||||
ast_node(f, Field, field);
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
str = gb_string_appendc(str, sep);
|
str = gb_string_appendc(str, sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
str = write_expr_to_string(str, field);
|
str = write_expr_to_string(str, params[i]);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -3885,19 +3922,19 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = write_expr_to_string(str, vt->elem);
|
str = write_expr_to_string(str, vt->elem);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(f, Field, node);
|
case_ast_node(p, Parameter, node);
|
||||||
if (f->is_using) {
|
if (p->is_using) {
|
||||||
str = gb_string_appendc(str, "using ");
|
str = gb_string_appendc(str, "using ");
|
||||||
}
|
}
|
||||||
gb_for_array(i, f->names) {
|
gb_for_array(i, p->names) {
|
||||||
AstNode *name = f->names[i];
|
AstNode *name = p->names[i];
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
str = gb_string_appendc(str, ", ");
|
str = gb_string_appendc(str, ", ");
|
||||||
str = write_expr_to_string(str, name);
|
str = write_expr_to_string(str, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
str = gb_string_appendc(str, ": ");
|
str = gb_string_appendc(str, ": ");
|
||||||
str = write_expr_to_string(str, f->type);
|
str = write_expr_to_string(str, p->type);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ce, CallExpr, node);
|
case_ast_node(ce, CallExpr, node);
|
||||||
@@ -3916,7 +3953,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
|
|
||||||
case_ast_node(pt, ProcType, node);
|
case_ast_node(pt, ProcType, node);
|
||||||
str = gb_string_appendc(str, "proc(");
|
str = gb_string_appendc(str, "proc(");
|
||||||
str = write_fields_to_string(str, pt->params, ", ");
|
str = write_params_to_string(str, pt->params, ", ");
|
||||||
str = gb_string_appendc(str, ")");
|
str = gb_string_appendc(str, ")");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
@@ -3924,19 +3961,37 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = gb_string_appendc(str, "struct ");
|
str = gb_string_appendc(str, "struct ");
|
||||||
if (st->is_packed) str = gb_string_appendc(str, "#packed ");
|
if (st->is_packed) str = gb_string_appendc(str, "#packed ");
|
||||||
if (st->is_ordered) str = gb_string_appendc(str, "#ordered ");
|
if (st->is_ordered) str = gb_string_appendc(str, "#ordered ");
|
||||||
// str = write_fields_to_string(str, st->decl_list, ", ");
|
gb_for_array(i, st->decls) {
|
||||||
|
if (i > 0) {
|
||||||
|
str = gb_string_appendc(str, "; ");
|
||||||
|
}
|
||||||
|
str = write_expr_to_string(str, st->decls[i]);
|
||||||
|
}
|
||||||
|
// str = write_params_to_string(str, st->decl_list, ", ");
|
||||||
str = gb_string_appendc(str, "}");
|
str = gb_string_appendc(str, "}");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(st, RawUnionType, node);
|
case_ast_node(st, RawUnionType, node);
|
||||||
str = gb_string_appendc(str, "raw_union {");
|
str = gb_string_appendc(str, "raw_union {");
|
||||||
// str = write_fields_to_string(str, st->decl_list, ", ");
|
gb_for_array(i, st->decls) {
|
||||||
|
if (i > 0) {
|
||||||
|
str = gb_string_appendc(str, "; ");
|
||||||
|
}
|
||||||
|
str = write_expr_to_string(str, st->decls[i]);
|
||||||
|
}
|
||||||
|
// str = write_params_to_string(str, st->decl_list, ", ");
|
||||||
str = gb_string_appendc(str, "}");
|
str = gb_string_appendc(str, "}");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
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 = write_fields_to_string(str, st->decl_list, ", ");
|
gb_for_array(i, st->decls) {
|
||||||
|
if (i > 0) {
|
||||||
|
str = gb_string_appendc(str, "; ");
|
||||||
|
}
|
||||||
|
str = write_expr_to_string(str, st->decls[i]);
|
||||||
|
}
|
||||||
|
// str = write_params_to_string(str, st->decl_list, ", ");
|
||||||
str = gb_string_appendc(str, "}");
|
str = gb_string_appendc(str, "}");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+33
-19
@@ -11,14 +11,19 @@ void check_stmt(Checker *c, AstNode *node, u32 flags);
|
|||||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
|
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
|
||||||
|
|
||||||
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||||
|
if (stmts == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
struct Delay {
|
struct Delay {
|
||||||
Entity *e;
|
Entity *e;
|
||||||
DeclInfo *d;
|
DeclInfo *d;
|
||||||
};
|
};
|
||||||
gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
|
gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, gb_array_count(stmts));
|
||||||
gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator());
|
gbArray(Delay) delayed_type; gb_array_init_reserve(delayed_type, c->tmp_allocator, gb_array_count(stmts));
|
||||||
defer (gb_array_free(delayed_const));
|
|
||||||
defer (gb_array_free(delayed_type));
|
|
||||||
|
|
||||||
gb_for_array(i, stmts) {
|
gb_for_array(i, stmts) {
|
||||||
AstNode *node = stmts[i];
|
AstNode *node = stmts[i];
|
||||||
@@ -312,8 +317,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
|||||||
// NOTE(bill): Use the type of the operand
|
// NOTE(bill): Use the type of the operand
|
||||||
Type *t = operand->type;
|
Type *t = operand->type;
|
||||||
if (is_type_untyped(t)) {
|
if (is_type_untyped(t)) {
|
||||||
if (t == t_invalid) {
|
if (t == t_invalid || is_type_untyped_nil(t)) {
|
||||||
error(e->token, "Use of untyped thing in %.*s", LIT(context_name));
|
error(e->token, "Use of untyped nil in %.*s", LIT(context_name));
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -331,13 +336,17 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
|
void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
|
||||||
if ((lhs == NULL || lhs_count == 0) && gb_array_count(inits) == 0)
|
if ((lhs == NULL || lhs_count == 0) && (inits == NULL || gb_array_count(inits) == 0)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(bill): Do not use heap allocation here if I can help it
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
|
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||||
|
// an extra allocation
|
||||||
gbArray(Operand) operands;
|
gbArray(Operand) operands;
|
||||||
gb_array_init_reserve(operands, gb_heap_allocator(), 2*lhs_count);
|
gb_array_init_reserve(operands, c->tmp_allocator, 2*lhs_count);
|
||||||
defer (gb_array_free(operands));
|
|
||||||
|
|
||||||
gb_for_array(i, inits) {
|
gb_for_array(i, inits) {
|
||||||
AstNode *rhs = inits[i];
|
AstNode *rhs = inits[i];
|
||||||
@@ -907,10 +916,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bill): Do not use heap allocation here if I can help it
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
|
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||||
|
// an extra allocation
|
||||||
gbArray(Operand) operands;
|
gbArray(Operand) operands;
|
||||||
gb_array_init(operands, gb_heap_allocator());
|
gb_array_init_reserve(operands, c->tmp_allocator, 2 * gb_array_count(as->lhs));
|
||||||
defer (gb_array_free(operands));
|
|
||||||
|
|
||||||
gb_for_array(i, as->rhs) {
|
gb_for_array(i, as->rhs) {
|
||||||
AstNode *rhs = as->rhs[i];
|
AstNode *rhs = as->rhs[i];
|
||||||
@@ -1091,8 +1103,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
AstNode *stmt = bs->stmts[i];
|
AstNode *stmt = bs->stmts[i];
|
||||||
AstNode *default_stmt = NULL;
|
AstNode *default_stmt = NULL;
|
||||||
if (stmt->kind == AstNode_CaseClause) {
|
if (stmt->kind == AstNode_CaseClause) {
|
||||||
ast_node(c, CaseClause, stmt);
|
ast_node(cc, CaseClause, stmt);
|
||||||
if (gb_array_count(c->list) == 0) {
|
if (gb_array_count(cc->list) == 0) {
|
||||||
default_stmt = stmt;
|
default_stmt = stmt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1158,9 +1170,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
HashKey key = hash_exact_value(y.value);
|
HashKey key = hash_exact_value(y.value);
|
||||||
auto *found = map_get(&seen, key);
|
auto *found = map_get(&seen, key);
|
||||||
if (found != NULL) {
|
if (found != NULL) {
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
isize count = multi_map_count(&seen, key);
|
isize count = multi_map_count(&seen, key);
|
||||||
TypeAndToken *taps = gb_alloc_array(gb_heap_allocator(), TypeAndToken, count);
|
TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
|
||||||
defer (gb_free(gb_heap_allocator(), taps));
|
|
||||||
|
|
||||||
multi_map_get_all(&seen, key, taps);
|
multi_map_get_all(&seen, key, taps);
|
||||||
b32 continue_outer = false;
|
b32 continue_outer = false;
|
||||||
@@ -1227,8 +1241,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
AstNode *stmt = bs->stmts[i];
|
AstNode *stmt = bs->stmts[i];
|
||||||
AstNode *default_stmt = NULL;
|
AstNode *default_stmt = NULL;
|
||||||
if (stmt->kind == AstNode_CaseClause) {
|
if (stmt->kind == AstNode_CaseClause) {
|
||||||
ast_node(c, CaseClause, stmt);
|
ast_node(cc, CaseClause, stmt);
|
||||||
if (gb_array_count(c->list) == 0) {
|
if (gb_array_count(cc->list) == 0) {
|
||||||
default_stmt = stmt;
|
default_stmt = stmt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+47
-10
@@ -22,9 +22,9 @@ enum BasicKind {
|
|||||||
Basic_UntypedBool,
|
Basic_UntypedBool,
|
||||||
Basic_UntypedInteger,
|
Basic_UntypedInteger,
|
||||||
Basic_UntypedFloat,
|
Basic_UntypedFloat,
|
||||||
Basic_UntypedPointer,
|
|
||||||
Basic_UntypedString,
|
Basic_UntypedString,
|
||||||
Basic_UntypedRune,
|
Basic_UntypedRune,
|
||||||
|
Basic_UntypedNil,
|
||||||
|
|
||||||
Basic_Count,
|
Basic_Count,
|
||||||
|
|
||||||
@@ -309,9 +309,9 @@ gb_global Type basic_types[] = {
|
|||||||
{Type_Basic, 0, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
{Type_Basic, 0, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
||||||
{Type_Basic, 0, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
|
{Type_Basic, 0, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
|
||||||
{Type_Basic, 0, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
|
{Type_Basic, 0, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
|
||||||
{Type_Basic, 0, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}},
|
|
||||||
{Type_Basic, 0, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}},
|
{Type_Basic, 0, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}},
|
||||||
{Type_Basic, 0, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}},
|
{Type_Basic, 0, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}},
|
||||||
|
{Type_Basic, 0, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}},
|
||||||
};
|
};
|
||||||
|
|
||||||
gb_global Type basic_type_aliases[] = {
|
gb_global Type basic_type_aliases[] = {
|
||||||
@@ -339,9 +339,9 @@ gb_global Type *t_any = &basic_types[Basic_any];
|
|||||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||||
gb_global Type *t_untyped_pointer = &basic_types[Basic_UntypedPointer];
|
|
||||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||||
|
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||||
gb_global Type *t_byte = &basic_type_aliases[0];
|
gb_global Type *t_byte = &basic_type_aliases[0];
|
||||||
gb_global Type *t_rune = &basic_type_aliases[1];
|
gb_global Type *t_rune = &basic_type_aliases[1];
|
||||||
|
|
||||||
@@ -548,6 +548,11 @@ b32 is_type_any(Type *t) {
|
|||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
|
return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
|
||||||
}
|
}
|
||||||
|
b32 is_type_untyped_nil(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
b32 is_type_indexable(Type *t) {
|
b32 is_type_indexable(Type *t) {
|
||||||
@@ -555,12 +560,31 @@ b32 is_type_indexable(Type *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
b32 type_has_nil(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
switch (t->kind) {
|
||||||
|
case Type_Basic:
|
||||||
|
return is_type_rawptr(t);
|
||||||
|
|
||||||
|
case Type_Tuple:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case Type_Record:
|
||||||
|
switch (t->Record.kind) {
|
||||||
|
case TypeRecord_Enum:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
b32 is_type_comparable(Type *t) {
|
b32 is_type_comparable(Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
return true;
|
return t->kind != Basic_UntypedNil;
|
||||||
case Type_Pointer:
|
case Type_Pointer:
|
||||||
return true;
|
return true;
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
@@ -681,12 +705,12 @@ b32 are_types_identical(Type *x, Type *y) {
|
|||||||
Type *default_type(Type *type) {
|
Type *default_type(Type *type) {
|
||||||
if (type->kind == Type_Basic) {
|
if (type->kind == Type_Basic) {
|
||||||
switch (type->Basic.kind) {
|
switch (type->Basic.kind) {
|
||||||
case Basic_UntypedBool: return &basic_types[Basic_bool];
|
case Basic_UntypedBool: return t_bool;
|
||||||
case Basic_UntypedInteger: return &basic_types[Basic_int];
|
case Basic_UntypedInteger: return t_int;
|
||||||
case Basic_UntypedFloat: return &basic_types[Basic_f64];
|
case Basic_UntypedFloat: return t_f64;
|
||||||
case Basic_UntypedString: return &basic_types[Basic_string];
|
case Basic_UntypedString: return t_string;
|
||||||
case Basic_UntypedRune: return &basic_types[Basic_rune];
|
case Basic_UntypedRune: return t_rune;
|
||||||
case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
|
// case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
@@ -952,6 +976,17 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
return gb_clamp(size, 1, s.max_align);
|
return gb_clamp(size, 1, s.max_align);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Type_Tuple: {
|
||||||
|
i64 max = 1;
|
||||||
|
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||||
|
i64 align = type_align_of(s, allocator, t->Tuple.variables[i]->type);
|
||||||
|
if (max < align) {
|
||||||
|
max = align;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
} break;
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
switch (t->Record.kind) {
|
||||||
case TypeRecord_Struct:
|
case TypeRecord_Struct:
|
||||||
@@ -964,6 +999,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return max;
|
return max;
|
||||||
|
} else if (t->Record.field_count > 0) {
|
||||||
|
return type_align_of(s, allocator, t->Record.fields[0]->type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeRecord_Union: {
|
case TypeRecord_Union: {
|
||||||
|
|||||||
+12
-11
@@ -21,8 +21,9 @@ b32 ssa_gen_init(ssaGen *s, Checker *c) {
|
|||||||
// TODO(bill): generate appropriate output name
|
// TODO(bill): generate appropriate output name
|
||||||
int pos = cast(int)string_extension_position(c->parser->init_fullpath);
|
int pos = cast(int)string_extension_position(c->parser->init_fullpath);
|
||||||
gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text));
|
gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text));
|
||||||
if (err != gbFileError_None)
|
if (err != gbFileError_None) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -434,10 +435,10 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
|
ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
|
||||||
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_bool_ptr), packed);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr), size);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_bool_ptr), ordered);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_int_ptr), size);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_bool_ptr), packed);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr), align);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_bool_ptr), ordered);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
||||||
@@ -481,8 +482,8 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
{
|
{
|
||||||
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_int_ptr), size);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr), size);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr), align);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeRecord_RawUnion: {
|
case TypeRecord_RawUnion: {
|
||||||
@@ -490,8 +491,8 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
{
|
{
|
||||||
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 3, t_int_ptr), size);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 1, t_int_ptr), size);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr), align);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
||||||
@@ -605,8 +606,8 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
tag = ssa_add_local_generated(proc, t_type_info_tuple);
|
tag = ssa_add_local_generated(proc, t_type_info_tuple);
|
||||||
|
|
||||||
{
|
{
|
||||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 4, t_int_ptr), align);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, 2, t_int_ptr), align);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index);
|
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index);
|
||||||
|
|||||||
+16
-10
@@ -157,13 +157,7 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
|||||||
case Basic_string: ssa_fprintf(f, "%%..string"); break;
|
case Basic_string: ssa_fprintf(f, "%%..string"); break;
|
||||||
case Basic_uint: ssa_fprintf(f, "i%lld", word_bits); break;
|
case Basic_uint: ssa_fprintf(f, "i%lld", word_bits); break;
|
||||||
case Basic_int: ssa_fprintf(f, "i%lld", word_bits); break;
|
case Basic_int: ssa_fprintf(f, "i%lld", word_bits); break;
|
||||||
case Basic_any:
|
case Basic_any: ssa_fprintf(f, "%%..any"); break;
|
||||||
ssa_fprintf(f, "{");
|
|
||||||
ssa_print_type(f, m, t_type_info_ptr);
|
|
||||||
ssa_fprintf(f, ", ");
|
|
||||||
ssa_print_type(f, m, t_rawptr);
|
|
||||||
ssa_fprintf(f, "}");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
@@ -491,7 +485,8 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
GB_PANIC("Invalid ExactValue: %d", value.kind);
|
ssa_fprintf(f, "zeroinitializer");
|
||||||
|
// GB_PANIC("Invalid ExactValue: %d", value.kind);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,6 +533,10 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ssaValue_Nil:
|
||||||
|
ssa_fprintf(f, "zeroinitializer");
|
||||||
|
break;
|
||||||
|
|
||||||
case ssaValue_TypeName:
|
case ssaValue_TypeName:
|
||||||
ssa_print_encoded_local(f, value->TypeName.name);
|
ssa_print_encoded_local(f, value->TypeName.name);
|
||||||
break;
|
break;
|
||||||
@@ -1045,9 +1044,16 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) {
|
|||||||
ssa_fprintf(f, " = type {i8*, ");
|
ssa_fprintf(f, " = type {i8*, ");
|
||||||
ssa_print_type(f, m, t_int);
|
ssa_print_type(f, m, t_int);
|
||||||
ssa_fprintf(f, "} ; Basic_string\n");
|
ssa_fprintf(f, "} ; Basic_string\n");
|
||||||
|
|
||||||
ssa_print_encoded_local(f, make_string("..rawptr"));
|
ssa_print_encoded_local(f, make_string("..rawptr"));
|
||||||
ssa_fprintf(f, " = type i8* ; Basic_rawptr\n\n");
|
ssa_fprintf(f, " = type i8* ; Basic_rawptr\n");
|
||||||
|
|
||||||
|
ssa_print_encoded_local(f, make_string("..any"));
|
||||||
|
ssa_fprintf(f, " = type {");
|
||||||
|
ssa_print_type(f, m, t_type_info_ptr);
|
||||||
|
ssa_fprintf(f, ", ");
|
||||||
|
ssa_print_type(f, m, t_rawptr);
|
||||||
|
ssa_fprintf(f, "} ; Basic_any\n");
|
||||||
|
|
||||||
|
|
||||||
gb_for_array(member_index, m->members.entries) {
|
gb_for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries[member_index];
|
auto *entry = &m->members.entries[member_index];
|
||||||
|
|||||||
+24
-5
@@ -298,6 +298,7 @@ enum ssaValueKind {
|
|||||||
|
|
||||||
ssaValue_Constant,
|
ssaValue_Constant,
|
||||||
ssaValue_ConstantSlice,
|
ssaValue_ConstantSlice,
|
||||||
|
ssaValue_Nil,
|
||||||
ssaValue_TypeName,
|
ssaValue_TypeName,
|
||||||
ssaValue_Global,
|
ssaValue_Global,
|
||||||
ssaValue_Param,
|
ssaValue_Param,
|
||||||
@@ -323,6 +324,9 @@ struct ssaValue {
|
|||||||
ssaValue *backing_array;
|
ssaValue *backing_array;
|
||||||
i64 count;
|
i64 count;
|
||||||
} ConstantSlice;
|
} ConstantSlice;
|
||||||
|
struct {
|
||||||
|
Type *type;
|
||||||
|
} Nil;
|
||||||
struct {
|
struct {
|
||||||
String name;
|
String name;
|
||||||
Type * type;
|
Type * type;
|
||||||
@@ -540,6 +544,8 @@ Type *ssa_type(ssaValue *value) {
|
|||||||
return value->Constant.type;
|
return value->Constant.type;
|
||||||
case ssaValue_ConstantSlice:
|
case ssaValue_ConstantSlice:
|
||||||
return value->ConstantSlice.type;
|
return value->ConstantSlice.type;
|
||||||
|
case ssaValue_Nil:
|
||||||
|
return value->Nil.type;
|
||||||
case ssaValue_TypeName:
|
case ssaValue_TypeName:
|
||||||
return value->TypeName.type;
|
return value->TypeName.type;
|
||||||
case ssaValue_Global:
|
case ssaValue_Global:
|
||||||
@@ -643,6 +649,12 @@ ssaValue *ssa_make_value_param(gbAllocator a, ssaProcedure *parent, Entity *e) {
|
|||||||
v->Param.type = e->type;
|
v->Param.type = e->type;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
ssaValue *ssa_make_value_nil(gbAllocator a, Type *type) {
|
||||||
|
ssaValue *v = ssa_alloc_value(a, ssaValue_Nil);
|
||||||
|
v->Nil.type = type;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ssaValue *ssa_make_instr_local(ssaProcedure *p, Entity *e, b32 zero_initialized) {
|
ssaValue *ssa_make_instr_local(ssaProcedure *p, Entity *e, b32 zero_initialized) {
|
||||||
@@ -975,11 +987,8 @@ ssaValue *ssa_emit_comment(ssaProcedure *p, String text) {
|
|||||||
ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
|
ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
|
||||||
ssaBlock *b = proc->decl_block; // all variables must be in the first block
|
ssaBlock *b = proc->decl_block; // all variables must be in the first block
|
||||||
ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
|
ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
|
||||||
ssaValue *zero = ssa_make_instr_zero_init(proc, instr);
|
|
||||||
instr->Instr.parent = b;
|
instr->Instr.parent = b;
|
||||||
zero ->Instr.parent = b;
|
|
||||||
gb_array_append(b->instrs, instr);
|
gb_array_append(b->instrs, instr);
|
||||||
gb_array_append(b->instrs, zero);
|
|
||||||
|
|
||||||
// if (zero_initialized) {
|
// if (zero_initialized) {
|
||||||
ssa_emit_zero_init(proc, instr);
|
ssa_emit_zero_init(proc, instr);
|
||||||
@@ -1301,9 +1310,9 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *
|
|||||||
|
|
||||||
if (are_types_identical(a, b)) {
|
if (are_types_identical(a, b)) {
|
||||||
// NOTE(bill): No need for a conversion
|
// NOTE(bill): No need for a conversion
|
||||||
} else if (left->kind == ssaValue_Constant) {
|
} else if (left->kind == ssaValue_Constant || left->kind == ssaValue_Nil) {
|
||||||
left = ssa_emit_conv(proc, left, ssa_type(right));
|
left = ssa_emit_conv(proc, left, ssa_type(right));
|
||||||
} else if (right->kind == ssaValue_Constant) {
|
} else if (right->kind == ssaValue_Constant || right->kind == ssaValue_Nil) {
|
||||||
right = ssa_emit_conv(proc, right, ssa_type(left));
|
right = ssa_emit_conv(proc, right, ssa_type(left));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1880,6 +1889,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
|||||||
if (is_type_any(dst)) {
|
if (is_type_any(dst)) {
|
||||||
ssaValue *result = ssa_add_local_generated(proc, t_any);
|
ssaValue *result = ssa_add_local_generated(proc, t_any);
|
||||||
|
|
||||||
|
if (is_type_untyped_nil(src)) {
|
||||||
|
return ssa_emit_load(proc, result);
|
||||||
|
}
|
||||||
|
|
||||||
ssaValue *data = NULL;
|
ssaValue *data = NULL;
|
||||||
if (value->kind == ssaValue_Instr &&
|
if (value->kind == ssaValue_Instr &&
|
||||||
value->Instr.kind == ssaInstr_Load) {
|
value->Instr.kind == ssaInstr_Load) {
|
||||||
@@ -1905,6 +1918,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
|||||||
return ssa_emit_load(proc, result);
|
return ssa_emit_load(proc, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_untyped_nil(src) && type_has_nil(dst)) {
|
||||||
|
return ssa_make_value_nil(proc->module->allocator, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
|
gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
|
||||||
gb_printf_err("Not Identical %s != %s\n", type_to_string(src), type_to_string(dst));
|
gb_printf_err("Not Identical %s != %s\n", type_to_string(src), type_to_string(dst));
|
||||||
@@ -2035,6 +2052,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
||||||
LIT(token.pos.file), token.pos.line, token.pos.column);
|
LIT(token.pos.file), token.pos.line, token.pos.column);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else if (e->kind == Entity_Nil) {
|
||||||
|
return ssa_make_value_nil(proc->module->allocator, tv->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *found = map_get(&proc->module->values, hash_pointer(e));
|
auto *found = map_get(&proc->module->values, hash_pointer(e));
|
||||||
|
|||||||
@@ -275,6 +275,8 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
|||||||
switch (op.kind) {
|
switch (op.kind) {
|
||||||
case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
|
case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
|
||||||
case Token_CmpOr: return make_exact_value_bool(x.value_bool || y.value_bool);
|
case Token_CmpOr: return make_exact_value_bool(x.value_bool || y.value_bool);
|
||||||
|
case Token_And: return make_exact_value_bool(x.value_bool & y.value_bool);
|
||||||
|
case Token_Or: return make_exact_value_bool(x.value_bool | y.value_bool);
|
||||||
default: goto error;
|
default: goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+90
-80
@@ -131,7 +131,7 @@ AST_NODE_KIND(_ExprBegin, "", struct{}) \
|
|||||||
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
||||||
AST_NODE_KIND(CallExpr, "call expression", struct { \
|
AST_NODE_KIND(CallExpr, "call expression", struct { \
|
||||||
AstNode *proc; \
|
AstNode *proc; \
|
||||||
gbArray(AstNode *) args; \
|
AstNodeArray args; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
Token ellipsis; \
|
Token ellipsis; \
|
||||||
CallExprKind kind; \
|
CallExprKind kind; \
|
||||||
@@ -256,7 +256,7 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \
|
|||||||
AST_NODE_KIND(ForeignSystemLibrary, "foreign system library", struct { Token token, filepath; }) \
|
AST_NODE_KIND(ForeignSystemLibrary, "foreign system library", struct { Token token, filepath; }) \
|
||||||
AST_NODE_KIND(_DeclEnd, "", struct{}) \
|
AST_NODE_KIND(_DeclEnd, "", struct{}) \
|
||||||
AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
||||||
AST_NODE_KIND(Field, "field", struct { \
|
AST_NODE_KIND(Parameter, "parameter", struct { \
|
||||||
AstNodeArray names; \
|
AstNodeArray names; \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
b32 is_using; \
|
b32 is_using; \
|
||||||
@@ -444,11 +444,11 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->ImportDecl.token;
|
return node->ImportDecl.token;
|
||||||
case AstNode_ForeignSystemLibrary:
|
case AstNode_ForeignSystemLibrary:
|
||||||
return node->ForeignSystemLibrary.token;
|
return node->ForeignSystemLibrary.token;
|
||||||
case AstNode_Field: {
|
case AstNode_Parameter: {
|
||||||
if (node->Field.names)
|
if (node->Parameter.names)
|
||||||
return ast_node_token(node->Field.names[0]);
|
return ast_node_token(node->Parameter.names[0]);
|
||||||
else
|
else
|
||||||
return ast_node_token(node->Field.type);
|
return ast_node_token(node->Parameter.type);
|
||||||
}
|
}
|
||||||
case AstNode_ProcType:
|
case AstNode_ProcType:
|
||||||
return node->ProcType.token;
|
return node->ProcType.token;
|
||||||
@@ -545,7 +545,7 @@ gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, gbArray(AstNode *)args, Token open, Token close, Token ellipsis) {
|
gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args, Token open, Token close, Token ellipsis) {
|
||||||
AstNode *result = make_node(f, AstNode_CallExpr);
|
AstNode *result = make_node(f, AstNode_CallExpr);
|
||||||
result->CallExpr.proc = proc;
|
result->CallExpr.proc = proc;
|
||||||
result->CallExpr.args = args;
|
result->CallExpr.args = args;
|
||||||
@@ -823,11 +823,11 @@ gb_inline AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
|
gb_inline AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
|
||||||
AstNode *result = make_node(f, AstNode_Field);
|
AstNode *result = make_node(f, AstNode_Parameter);
|
||||||
result->Field.names = names;
|
result->Parameter.names = names;
|
||||||
result->Field.type = type;
|
result->Parameter.type = type;
|
||||||
result->Field.is_using = is_using;
|
result->Parameter.is_using = is_using;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -961,6 +961,19 @@ gb_inline Token expect_token(AstFile *f, TokenKind kind) {
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_inline Token expect_token_after(AstFile *f, TokenKind kind, char *msg) {
|
||||||
|
Token prev = f->curr_token;
|
||||||
|
if (prev.kind != kind) {
|
||||||
|
syntax_error(f->curr_token, "Expected `%.*s` after %s, got `%.*s`",
|
||||||
|
LIT(token_strings[kind]),
|
||||||
|
msg,
|
||||||
|
LIT(token_strings[prev.kind]));
|
||||||
|
}
|
||||||
|
next_token(f);
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline Token expect_operator(AstFile *f) {
|
gb_inline Token expect_operator(AstFile *f) {
|
||||||
Token prev = f->curr_token;
|
Token prev = f->curr_token;
|
||||||
if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
|
if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
|
||||||
@@ -1650,7 +1663,7 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
|
|||||||
|
|
||||||
expression = call;
|
expression = call;
|
||||||
} else */{
|
} else */{
|
||||||
AstNode *right = parse_binary_expr(f, false, prec+1);
|
right = parse_binary_expr(f, false, prec+1);
|
||||||
gbArray(AstNode *) args;
|
gbArray(AstNode *) args;
|
||||||
gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
|
gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
|
||||||
gb_array_append(args, expression);
|
gb_array_append(args, expression);
|
||||||
@@ -1841,58 +1854,54 @@ AstNode *parse_proc_type(AstFile *f) {
|
|||||||
return make_proc_type(f, proc_token, params, results);
|
return make_proc_type(f, proc_token, params, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_field_decl(AstFile *f) {
|
|
||||||
b32 is_using = false;
|
|
||||||
if (allow_token(f, Token_using)) {
|
|
||||||
is_using = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNodeArray names = parse_lhs_expr_list(f);
|
|
||||||
if (gb_array_count(names) == 0) {
|
|
||||||
syntax_error(f->curr_token, "Empty field declaration");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gb_array_count(names) > 1 && is_using) {
|
|
||||||
syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
|
|
||||||
is_using = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
expect_token(f, Token_Colon);
|
|
||||||
|
|
||||||
AstNode *type = NULL;
|
|
||||||
if (f->curr_token.kind == Token_Ellipsis) {
|
|
||||||
Token ellipsis = f->curr_token;
|
|
||||||
next_token(f);
|
|
||||||
type = parse_type_attempt(f);
|
|
||||||
if (type == NULL) {
|
|
||||||
syntax_error(f->curr_token, "variadic parameter is missing a type after `..`");
|
|
||||||
type = make_bad_expr(f, ellipsis, f->curr_token);
|
|
||||||
} else {
|
|
||||||
if (gb_array_count(names) > 1) {
|
|
||||||
syntax_error(f->curr_token, "mutliple variadic parameters, only `..`");
|
|
||||||
} else {
|
|
||||||
type = make_ellipsis(f, ellipsis, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type = parse_type_attempt(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == NULL) {
|
|
||||||
syntax_error(f->curr_token, "Expected a type for this field declaration");
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *field = make_field(f, names, type, is_using);
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNodeArray parse_parameter_list(AstFile *f) {
|
AstNodeArray parse_parameter_list(AstFile *f) {
|
||||||
AstNodeArray params = make_ast_node_array(f);
|
AstNodeArray params = make_ast_node_array(f);
|
||||||
|
|
||||||
while (f->curr_token.kind == Token_Identifier ||
|
while (f->curr_token.kind == Token_Identifier ||
|
||||||
f->curr_token.kind == Token_using) {
|
f->curr_token.kind == Token_using) {
|
||||||
AstNode *field = parse_field_decl(f);
|
b32 is_using = false;
|
||||||
gb_array_append(params, field);
|
if (allow_token(f, Token_using)) {
|
||||||
|
is_using = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNodeArray names = parse_lhs_expr_list(f);
|
||||||
|
if (gb_array_count(names) == 0) {
|
||||||
|
syntax_error(f->curr_token, "Empty parameter declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gb_array_count(names) > 1 && is_using) {
|
||||||
|
syntax_error(f->curr_token, "Cannot apply `using` to more than one of the same type");
|
||||||
|
is_using = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect_token_after(f, Token_Colon, "parameter list");
|
||||||
|
|
||||||
|
AstNode *type = NULL;
|
||||||
|
if (f->curr_token.kind == Token_Ellipsis) {
|
||||||
|
Token ellipsis = f->curr_token;
|
||||||
|
next_token(f);
|
||||||
|
type = parse_type_attempt(f);
|
||||||
|
if (type == NULL) {
|
||||||
|
syntax_error(f->curr_token, "variadic parameter is missing a type after `..`");
|
||||||
|
type = make_bad_expr(f, ellipsis, f->curr_token);
|
||||||
|
} else {
|
||||||
|
if (gb_array_count(names) > 1) {
|
||||||
|
syntax_error(f->curr_token, "mutliple variadic parameters, only `..`");
|
||||||
|
} else {
|
||||||
|
type = make_ellipsis(f, ellipsis, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = parse_type_attempt(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (type == NULL) {
|
||||||
|
syntax_error(f->curr_token, "Expected a type for this parameter declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_array_append(params, make_parameter(f, names, type, is_using));
|
||||||
if (f->curr_token.kind != Token_Comma) {
|
if (f->curr_token.kind != Token_Comma) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2011,7 +2020,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
|||||||
b32 is_packed = false;
|
b32 is_packed = false;
|
||||||
b32 is_ordered = false;
|
b32 is_ordered = false;
|
||||||
while (allow_token(f, Token_Hash)) {
|
while (allow_token(f, Token_Hash)) {
|
||||||
Token tag = expect_token(f, Token_Identifier);
|
Token tag = expect_token_after(f, Token_Identifier, "`#`");
|
||||||
if (tag.string == "packed") {
|
if (tag.string == "packed") {
|
||||||
if (is_packed) {
|
if (is_packed) {
|
||||||
syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
|
syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
|
||||||
@@ -2031,7 +2040,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
|||||||
syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering");
|
syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering");
|
||||||
}
|
}
|
||||||
|
|
||||||
Token open = expect_token(f, Token_OpenBrace);
|
Token open = expect_token_after(f, Token_OpenBrace, "`struct`");
|
||||||
isize decl_count = 0;
|
isize decl_count = 0;
|
||||||
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
|
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
|
||||||
Token close = expect_token(f, Token_CloseBrace);
|
Token close = expect_token(f, Token_CloseBrace);
|
||||||
@@ -2041,7 +2050,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
|||||||
|
|
||||||
case Token_union: {
|
case Token_union: {
|
||||||
Token token = expect_token(f, Token_union);
|
Token token = expect_token(f, Token_union);
|
||||||
Token open = expect_token(f, Token_OpenBrace);
|
Token open = expect_token_after(f, Token_OpenBrace, "`union`");
|
||||||
isize decl_count = 0;
|
isize decl_count = 0;
|
||||||
AstNodeArray decls = parse_struct_params(f, &decl_count, false);
|
AstNodeArray decls = parse_struct_params(f, &decl_count, false);
|
||||||
Token close = expect_token(f, Token_CloseBrace);
|
Token close = expect_token(f, Token_CloseBrace);
|
||||||
@@ -2050,7 +2059,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Token_raw_union: {
|
case Token_raw_union: {
|
||||||
Token token = expect_token(f, Token_raw_union);
|
Token token = expect_token_after(f, Token_OpenBrace, "`raw_union`");
|
||||||
Token open = expect_token(f, Token_OpenBrace);
|
Token open = expect_token(f, Token_OpenBrace);
|
||||||
isize decl_count = 0;
|
isize decl_count = 0;
|
||||||
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
|
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
|
||||||
@@ -2070,7 +2079,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
|||||||
|
|
||||||
AstNodeArray fields = make_ast_node_array(f);
|
AstNodeArray fields = make_ast_node_array(f);
|
||||||
|
|
||||||
open = expect_token(f, Token_OpenBrace);
|
open = expect_token_after(f, Token_OpenBrace, "`enum`");
|
||||||
|
|
||||||
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) {
|
||||||
@@ -2161,7 +2170,7 @@ Token parse_procedure_signature(AstFile *f,
|
|||||||
Token proc_token = expect_token(f, Token_proc);
|
Token proc_token = expect_token(f, Token_proc);
|
||||||
expect_token(f, Token_OpenParen);
|
expect_token(f, Token_OpenParen);
|
||||||
*params = parse_parameter_list(f);
|
*params = parse_parameter_list(f);
|
||||||
expect_token(f, Token_CloseParen);
|
expect_token_after(f, Token_CloseParen, "parameter list");
|
||||||
*results = parse_results(f);
|
*results = parse_results(f);
|
||||||
return proc_token;
|
return proc_token;
|
||||||
}
|
}
|
||||||
@@ -2210,17 +2219,17 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
|
|||||||
AstNodeArray values = NULL;
|
AstNodeArray values = NULL;
|
||||||
AstNode *type = NULL;
|
AstNode *type = NULL;
|
||||||
|
|
||||||
gb_for_array(i, names) {
|
// gb_for_array(i, names) {
|
||||||
AstNode *name = names[i];
|
// AstNode *name = names[i];
|
||||||
if (name->kind == AstNode_Ident) {
|
// if (name->kind == AstNode_Ident) {
|
||||||
String n = name->Ident.string;
|
// String n = name->Ident.string;
|
||||||
// NOTE(bill): Check for reserved identifiers
|
// // NOTE(bill): Check for reserved identifiers
|
||||||
if (n == "context") {
|
// if (n == "context") {
|
||||||
syntax_error(ast_node_token(name), "`context` is a reserved identifier");
|
// syntax_error(ast_node_token(name), "`context` is a reserved identifier");
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (allow_token(f, Token_Colon)) {
|
if (allow_token(f, Token_Colon)) {
|
||||||
if (!allow_token(f, Token_type)) {
|
if (!allow_token(f, Token_type)) {
|
||||||
@@ -2258,8 +2267,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
|
|||||||
// NOTE(bill): Do not fail though
|
// NOTE(bill): Do not fail though
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *type = parse_type(f);
|
return make_type_decl(f, token, names[0], parse_type(f));
|
||||||
return make_type_decl(f, token, names[0], type);
|
|
||||||
} else if (f->curr_token.kind == Token_proc &&
|
} else if (f->curr_token.kind == Token_proc &&
|
||||||
is_mutable == false) {
|
is_mutable == false) {
|
||||||
// NOTE(bill): Procedure declarations
|
// NOTE(bill): Procedure declarations
|
||||||
@@ -2434,6 +2442,7 @@ AstNode *parse_case_clause(AstFile *f) {
|
|||||||
expect_token(f, Token_default);
|
expect_token(f, Token_default);
|
||||||
}
|
}
|
||||||
expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
|
expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
|
||||||
|
// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
|
||||||
AstNodeArray stmts = parse_stmt_list(f);
|
AstNodeArray stmts = parse_stmt_list(f);
|
||||||
|
|
||||||
return make_case_clause(f, token, list, stmts);
|
return make_case_clause(f, token, list, stmts);
|
||||||
@@ -2449,6 +2458,7 @@ AstNode *parse_type_case_clause(AstFile *f) {
|
|||||||
expect_token(f, Token_default);
|
expect_token(f, Token_default);
|
||||||
}
|
}
|
||||||
expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
|
expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
|
||||||
|
// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
|
||||||
AstNodeArray stmts = parse_stmt_list(f);
|
AstNodeArray stmts = parse_stmt_list(f);
|
||||||
|
|
||||||
return make_case_clause(f, token, clause, stmts);
|
return make_case_clause(f, token, clause, stmts);
|
||||||
@@ -3069,7 +3079,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
|
|||||||
p->init_fullpath = init_fullpath;
|
p->init_fullpath = init_fullpath;
|
||||||
|
|
||||||
{
|
{
|
||||||
String s = get_fullpath_core(gb_heap_allocator(), make_string("runtime.odin"));
|
String s = get_fullpath_core(gb_heap_allocator(), make_string("_preload.odin"));
|
||||||
ImportedFile runtime_file = {s, s, init_pos};
|
ImportedFile runtime_file = {s, s, init_pos};
|
||||||
gb_array_append(p->imports, runtime_file);
|
gb_array_append(p->imports, runtime_file);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -190,11 +190,11 @@ void print_ast(AstNode *node, isize indent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AstNode_Field:
|
case AstNode_Parameter:
|
||||||
gb_for_array(i, node->Field.names) {
|
gb_for_array(i, node->Parameter.names) {
|
||||||
print_ast(node->Field.names[i], indent+1);
|
print_ast(node->Parameter.names[i], indent+1);
|
||||||
}
|
}
|
||||||
print_ast(node->Field.type, indent);
|
print_ast(node->Parameter.type, indent);
|
||||||
break;
|
break;
|
||||||
case AstNode_PointerType:
|
case AstNode_PointerType:
|
||||||
print_indent(indent);
|
print_indent(indent);
|
||||||
|
|||||||
+7548
-7544
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user