mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-04 12:07:45 +00:00
Untyped nil
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -254,3 +254,4 @@ paket-files/
|
||||
*.sln
|
||||
!misc/llvm-bim/lli.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
|
||||
rem -DDISPLAY_TIMING
|
||||
) else ( rem Release
|
||||
set compiler_flags=%compiler_flags% -O2 -MT
|
||||
set compiler_flags=%compiler_flags% -O2 -MT -Z7
|
||||
)
|
||||
|
||||
set compiler_warnings= ^
|
||||
-we4013 -we4706 ^
|
||||
-we4013 -we4706 -we4002 ^
|
||||
-wd4100 -wd4127 -wd4189 ^
|
||||
-wd4201 -wd4204 -wd4244 ^
|
||||
-wd4306 ^
|
||||
-wd4480 ^
|
||||
-wd4456 -wd4457 -wd4480 ^
|
||||
-wd4505 -wd4512 -wd4550
|
||||
|
||||
set compiler_includes=
|
||||
@@ -31,7 +31,7 @@ set linker_flags= -incremental:no -opt:ref -subsystem:console
|
||||
if %release_mode% EQU 0 ( rem Debug
|
||||
set linker_flags=%linker_flags% -debug
|
||||
) else ( rem Release
|
||||
set linker_flags=%linker_flags%
|
||||
set linker_flags=%linker_flags% -debug
|
||||
)
|
||||
|
||||
set compiler_settings=%compiler_includes% %compiler_flags% %compiler_warnings%
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#import "fmt.odin"
|
||||
#import "utf8.odin"
|
||||
#import "hash.odin"
|
||||
#import "mem.odin"
|
||||
#import "game.odin"
|
||||
|
||||
A :: {2}f32{1, 2}
|
||||
B :: {2}f32{3, 4}
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("Hellope")
|
||||
Fruit :: union {
|
||||
A: int
|
||||
B: f32
|
||||
C: struct {
|
||||
x: int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
|
||||
c_class_name := class_name.data
|
||||
w.c_title = to_c_string(title)
|
||||
|
||||
instance := GetModuleHandleA(null)
|
||||
instance := GetModuleHandleA(nil)
|
||||
|
||||
w.wc = WNDCLASSEXA{
|
||||
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,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
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()
|
||||
return w, false
|
||||
}
|
||||
@@ -92,7 +92,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: win32.WNDPROC)
|
||||
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)
|
||||
wglMakeCurrent(w.dc, w.opengl_context)
|
||||
|
||||
@@ -154,7 +154,7 @@ run :: proc() {
|
||||
prev_time = curr_time
|
||||
|
||||
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 {
|
||||
running = false
|
||||
}
|
||||
|
||||
66
code/old_demos/demo004.odin
Normal file
66
code/old_demos/demo004.odin
Normal file
@@ -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 {
|
||||
fields: []Member
|
||||
packed: bool
|
||||
ordered: bool
|
||||
size: int // in bytes
|
||||
align: int // in bytes
|
||||
packed: bool
|
||||
ordered: bool
|
||||
}
|
||||
|
||||
Named: struct #ordered {
|
||||
@@ -60,15 +60,15 @@ Type_Info :: union {
|
||||
Union: Record
|
||||
Raw_Union: Record
|
||||
Enum: struct #ordered {
|
||||
base: ^Type_Info
|
||||
base: ^Type_Info
|
||||
values: []i64
|
||||
names: []string
|
||||
}
|
||||
}
|
||||
|
||||
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||
if info == null {
|
||||
return null
|
||||
if info == nil {
|
||||
return nil
|
||||
}
|
||||
match type i : info {
|
||||
case Type_Info.Named:
|
||||
@@ -142,7 +142,7 @@ current_context :: proc() -> Context { // Copy of context
|
||||
__check_context :: proc() {
|
||||
c := ^__context
|
||||
|
||||
if c.allocator.procedure == null {
|
||||
if c.allocator.procedure == nil {
|
||||
c.allocator = __default_allocator()
|
||||
}
|
||||
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 {
|
||||
__check_context()
|
||||
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 {
|
||||
__check_context()
|
||||
a := current_context().allocator
|
||||
if ptr != null {
|
||||
if ptr != nil {
|
||||
a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
|
||||
}
|
||||
}
|
||||
free_all :: proc() #inline {
|
||||
__check_context()
|
||||
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 {
|
||||
if old_memory == null {
|
||||
if old_memory == nil {
|
||||
return alloc_align(new_size, alignment)
|
||||
}
|
||||
|
||||
if new_size == 0 {
|
||||
free(old_memory)
|
||||
return null
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
if new_memory == null {
|
||||
return null
|
||||
if new_memory == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
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:
|
||||
os.heap_free(mem.allocation_header(old_memory))
|
||||
return null
|
||||
return nil
|
||||
|
||||
case FREE_ALL:
|
||||
// NOTE(bill): Does nothing
|
||||
@@ -234,13 +234,13 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
||||
return mem.zero(ptr, size)
|
||||
}
|
||||
|
||||
return null
|
||||
return nil
|
||||
}
|
||||
|
||||
__default_allocator :: proc() -> Allocator {
|
||||
return Allocator{
|
||||
procedure = __default_allocator_proc,
|
||||
data = null,
|
||||
data = nil,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
|
||||
}
|
||||
|
||||
print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||
if ti == null { return }
|
||||
if ti == nil { return }
|
||||
|
||||
using Type_Info
|
||||
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)
|
||||
case Procedure:
|
||||
print_string_to_buffer(buf, "proc")
|
||||
if info.params == null {
|
||||
if info.params == nil {
|
||||
print_string_to_buffer(buf, "()")
|
||||
} else {
|
||||
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)
|
||||
if count == 1 { print_string_to_buffer(buf, ")") }
|
||||
}
|
||||
if info.results != null {
|
||||
if info.results != nil {
|
||||
print_string_to_buffer(buf, " -> ")
|
||||
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
|
||||
match type info : arg.type_info {
|
||||
case Named:
|
||||
@@ -352,7 +356,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
case Integer:
|
||||
if info.signed {
|
||||
i: i64 = 0;
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
match info.size {
|
||||
case 1: i = (arg.data as ^i8)^ 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)
|
||||
} else {
|
||||
i: u64 = 0;
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
match info.size {
|
||||
case 1: i = (arg.data as ^u8)^ 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:
|
||||
f: f64 = 0
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
match info.size {
|
||||
case 4: f = (arg.data as ^f32)^ 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:
|
||||
s := ""
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
s = (arg.data as ^string)^
|
||||
}
|
||||
print_string_to_buffer(buf, s)
|
||||
|
||||
case Boolean:
|
||||
v := false;
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
v = (arg.data as ^bool)^
|
||||
}
|
||||
print_bool_to_buffer(buf, v)
|
||||
|
||||
case Pointer:
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
if arg.type_info == type_info(^Type_Info) {
|
||||
print_type_to_buffer(buf, (arg.data as ^^Type_Info)^)
|
||||
} else {
|
||||
print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
||||
}
|
||||
} else {
|
||||
print_pointer_to_buffer(buf, null)
|
||||
print_pointer_to_buffer(buf, nil)
|
||||
}
|
||||
|
||||
case Enum:
|
||||
@@ -414,7 +418,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
match type i : info.base {
|
||||
case Integer:
|
||||
if i.signed {
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
match i.size {
|
||||
case 1: value = (arg.data as ^i8)^ 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 {
|
||||
if arg.data != null {
|
||||
if arg.data != nil {
|
||||
match i.size {
|
||||
case 1: value = (arg.data as ^u8)^ 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 {
|
||||
using Type_Info
|
||||
info = type_info_base(info)
|
||||
if info == null {
|
||||
if info == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -597,7 +601,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) {
|
||||
prev_string := false
|
||||
for i := 0; i < args.count; 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 {
|
||||
print_space_to_buffer(buf)
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ init_sub_arena :: proc(sub, parent: ^Arena, size: int) {
|
||||
}
|
||||
|
||||
free_arena :: proc(using a: ^Arena) {
|
||||
if backing.procedure != null {
|
||||
if backing.procedure != nil {
|
||||
push_allocator backing {
|
||||
free(memory.data)
|
||||
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 {
|
||||
fmt.fprintln(os.stderr, "Arena out of memory")
|
||||
return null
|
||||
return nil
|
||||
}
|
||||
|
||||
#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 null
|
||||
return nil
|
||||
}
|
||||
|
||||
begin_temp_arena_memory :: proc(a: ^Arena) -> Temp_Arena_Memory {
|
||||
|
||||
10
core/os.odin
10
core/os.odin
@@ -9,7 +9,7 @@ open :: proc(name: string) -> (File, bool) {
|
||||
using win32
|
||||
buf: [300]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
|
||||
|
||||
return f, success
|
||||
@@ -20,7 +20,7 @@ create :: proc(name: string) -> (File, bool) {
|
||||
buf: [300]byte
|
||||
copy(buf[:], name as []byte)
|
||||
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
|
||||
return f, success
|
||||
@@ -32,7 +32,7 @@ close :: proc(using f: ^File) {
|
||||
|
||||
write :: proc(using f: ^File, buf: []byte) -> bool {
|
||||
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)
|
||||
if data.data == null {
|
||||
if data.data == nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ read_entire_file :: proc(name: string) -> (string, bool) {
|
||||
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 {
|
||||
free(data.data)
|
||||
return "", false
|
||||
|
||||
@@ -12,14 +12,14 @@ Accept_Range :: struct {
|
||||
}
|
||||
|
||||
accept_ranges := [5]Accept_Range{
|
||||
Accept_Range{0x80, 0xbf},
|
||||
Accept_Range{0xa0, 0xbf},
|
||||
Accept_Range{0x80, 0x9f},
|
||||
Accept_Range{0x90, 0xbf},
|
||||
Accept_Range{0x80, 0x8f},
|
||||
{0x80, 0xbf},
|
||||
{0xa0, 0xbf},
|
||||
{0x80, 0x9f},
|
||||
{0x90, 0xbf},
|
||||
{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, // 0x10-0x1f
|
||||
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,8 +1,8 @@
|
||||
@echo off
|
||||
|
||||
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 10.0\VC\vcvarsall.bat" x86 1> NUL
|
||||
set _NO_DEBUG_HEAP=1
|
||||
|
||||
set path=w:\Odin\misc;%path%
|
||||
|
||||
@@ -33,6 +33,10 @@ struct Operand {
|
||||
BuiltinProcId builtin_id;
|
||||
};
|
||||
|
||||
b32 is_operand_nil(Operand *o) {
|
||||
return o->mode == Addressing_Value && o->type == t_untyped_nil;
|
||||
}
|
||||
|
||||
struct TypeAndValue {
|
||||
AddressingMode mode;
|
||||
Type *type;
|
||||
@@ -241,7 +245,9 @@ struct Checker {
|
||||
gbArray(ProcedureInfo) procs; // NOTE(bill): Procedures to check
|
||||
|
||||
gbArena arena;
|
||||
gbArena tmp_arena;
|
||||
gbAllocator allocator;
|
||||
gbAllocator tmp_allocator;
|
||||
|
||||
CheckerContext context;
|
||||
|
||||
@@ -501,9 +507,10 @@ void init_universal_scope(void) {
|
||||
}
|
||||
|
||||
// Constants
|
||||
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("null"), t_untyped_pointer, make_exact_value_pointer(NULL));
|
||||
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_entity(make_entity_nil(a, NULL, make_token_ident(make_string("nil")), t_untyped_nil));
|
||||
|
||||
// Builtin Procedures
|
||||
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;
|
||||
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->tmp_allocator = gb_arena_allocator(&c->tmp_arena);
|
||||
|
||||
c->global_scope = make_scope(universal_scope, c->allocator);
|
||||
c->context.scope = c->global_scope;
|
||||
@@ -705,6 +715,10 @@ void add_type_info_type(Checker *c, Type *t) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
// Types have already been added
|
||||
return;
|
||||
|
||||
@@ -10,6 +10,7 @@ enum BuiltinProcId;
|
||||
ENTITY_KIND(Procedure), \
|
||||
ENTITY_KIND(Builtin), \
|
||||
ENTITY_KIND(ImportName), \
|
||||
ENTITY_KIND(Nil), \
|
||||
ENTITY_KIND(Count),
|
||||
|
||||
|
||||
@@ -68,6 +69,8 @@ struct Entity {
|
||||
Scope *scope;
|
||||
b32 used;
|
||||
} ImportName;
|
||||
struct {
|
||||
} Nil;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -155,6 +158,12 @@ Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *
|
||||
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) {
|
||||
token.string = make_string("_");
|
||||
return make_entity_variable(a, file_scope, token, NULL);
|
||||
|
||||
@@ -68,13 +68,16 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
||||
if (is_type_untyped(src)) {
|
||||
switch (dst->kind) {
|
||||
case Type_Basic:
|
||||
if (operand->mode == Addressing_Constant)
|
||||
if (operand->mode == Addressing_Constant) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
if (is_type_untyped_nil(src)) {
|
||||
return type_has_nil(dst);
|
||||
}
|
||||
|
||||
// ^T <- rawptr
|
||||
// TODO(bill): Should C-style (not C++) pointer cast be allowed?
|
||||
// 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)) {
|
||||
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);
|
||||
target_type = default_type(operand->type);
|
||||
}
|
||||
@@ -229,14 +242,15 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
isize other_field_index = 0;
|
||||
Entity *using_index_expr = NULL;
|
||||
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
struct Delay {
|
||||
Entity *e;
|
||||
AstNode *t;
|
||||
};
|
||||
gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
|
||||
gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator());
|
||||
defer (gb_array_free(delayed_const));
|
||||
defer (gb_array_free(delayed_type));
|
||||
gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, other_field_count);
|
||||
gbArray(Delay) delayed_type; gb_array_init_reserve(delayed_type, c->tmp_allocator, other_field_count);
|
||||
|
||||
gb_for_array(decl_index, decls) {
|
||||
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));
|
||||
}
|
||||
|
||||
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_variadic_) {
|
||||
if (fields == NULL || gb_array_count(fields) == 0)
|
||||
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) {
|
||||
if (params == NULL || gb_array_count(params) == 0)
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
|
||||
isize variable_count = 0;
|
||||
gb_for_array(i, fields) {
|
||||
AstNode *field = fields[i];
|
||||
ast_node(f, Field, field);
|
||||
variable_count += gb_array_count(f->names);
|
||||
gb_for_array(i, params) {
|
||||
AstNode *field = params[i];
|
||||
ast_node(p, Parameter, field);
|
||||
variable_count += gb_array_count(p->names);
|
||||
}
|
||||
|
||||
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
|
||||
isize variable_index = 0;
|
||||
gb_for_array(i, fields) {
|
||||
AstNode *field = fields[i];
|
||||
ast_node(f, Field, field);
|
||||
AstNode *type_expr = f->type;
|
||||
gb_for_array(i, params) {
|
||||
ast_node(p, Parameter, params[i]);
|
||||
AstNode *type_expr = p->type;
|
||||
if (type_expr) {
|
||||
if (type_expr->kind == AstNode_Ellipsis) {
|
||||
type_expr = type_expr->Ellipsis.expr;
|
||||
if (i+1 == gb_array_count(fields)) {
|
||||
if (i+1 == gb_array_count(params)) {
|
||||
is_variadic = true;
|
||||
} 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);
|
||||
gb_for_array(j, f->names) {
|
||||
AstNode *name = f->names[j];
|
||||
gb_for_array(j, p->names) {
|
||||
AstNode *name = p->names[j];
|
||||
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);
|
||||
variables[variable_index++] = param;
|
||||
} 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
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
return;
|
||||
|
||||
case Entity_Nil:
|
||||
o->mode = Addressing_Value;
|
||||
break;
|
||||
|
||||
default:
|
||||
compiler_error("Compiler error: Unknown EntityKind");
|
||||
break;
|
||||
@@ -1184,15 +1201,20 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
||||
}
|
||||
break;
|
||||
|
||||
case Token_Mod:
|
||||
case Token_And:
|
||||
case Token_Or:
|
||||
case Token_Xor:
|
||||
case Token_AndNot:
|
||||
|
||||
case Token_ModEq:
|
||||
case Token_AndEq:
|
||||
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_AndNotEq:
|
||||
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) {
|
||||
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;
|
||||
if (is_type_unsigned(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) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
gbString err_str = NULL;
|
||||
defer ({
|
||||
if (err_str != NULL)
|
||||
@@ -1392,16 +1427,16 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
||||
|
||||
if (!defined) {
|
||||
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_string_free(type_string);
|
||||
}
|
||||
} else {
|
||||
gbString xt = type_to_string(x->type);
|
||||
gbString yt = type_to_string(y->type);
|
||||
defer(gb_string_free(xt));
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -1853,7 +1888,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
ExactValue b = y->value;
|
||||
|
||||
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)) {
|
||||
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->value.value_integer == 0) {
|
||||
// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
|
||||
extra_text = " - Did you want `null`?";
|
||||
if (make_string(expr_str) != "nil") { // HACK NOTE(bill): Just in case
|
||||
// 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);
|
||||
@@ -1989,36 +2034,27 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
||||
return;
|
||||
}
|
||||
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:
|
||||
switch (operand->type->Basic.kind) {
|
||||
case Basic_UntypedPointer:
|
||||
break;
|
||||
default:
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
case Basic_UntypedNil:
|
||||
if (!type_has_nil(target_type)) {
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
if (!type_has_nil(target_type)) {
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -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`");
|
||||
return false;
|
||||
}
|
||||
|
||||
add_type_info_type(c, type);
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
@@ -2993,10 +3030,12 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
return;
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
isize operand_count = 0;
|
||||
gbArray(Operand) operands;
|
||||
gb_array_init_reserve(operands, gb_heap_allocator(), 2*param_count);
|
||||
defer (gb_array_free(operands));
|
||||
gb_array_init_reserve(operands, c->tmp_allocator, 2*param_count);
|
||||
|
||||
gb_for_array(i, ce->args) {
|
||||
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);
|
||||
}
|
||||
|
||||
Operand o = {};
|
||||
check_expr_with_type_hint(c, &o, e, elem_type);
|
||||
check_assignment(c, &o, elem_type, context_name);
|
||||
Operand operand = {};
|
||||
check_expr_with_type_hint(c, &operand, e, elem_type);
|
||||
check_assignment(c, &operand, elem_type, context_name);
|
||||
|
||||
if (is_constant) {
|
||||
is_constant = o.mode == Addressing_Constant;
|
||||
is_constant = operand.mode == Addressing_Constant;
|
||||
}
|
||||
}
|
||||
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_not_tuple(c, o);
|
||||
if (o->mode == Addressing_NoValue) {
|
||||
AstNode *e = o->expr;
|
||||
gbString str = expr_to_string(e);
|
||||
gbString str = expr_to_string(o->expr);
|
||||
defer (gb_string_free(str));
|
||||
error(ast_node_token(e),
|
||||
error(ast_node_token(o->expr),
|
||||
"`%s` used as value or type", str);
|
||||
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_fields_to_string(gbString str, AstNodeArray fields, char *sep) {
|
||||
gb_for_array(i, fields) {
|
||||
AstNode *field = fields[i];
|
||||
ast_node(f, Field, field);
|
||||
gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
|
||||
gb_for_array(i, params) {
|
||||
ast_node(p, Parameter, params[i]);
|
||||
if (i > 0) {
|
||||
str = gb_string_appendc(str, sep);
|
||||
}
|
||||
|
||||
str = write_expr_to_string(str, field);
|
||||
str = write_expr_to_string(str, params[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -3885,19 +3922,19 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
str = write_expr_to_string(str, vt->elem);
|
||||
case_end;
|
||||
|
||||
case_ast_node(f, Field, node);
|
||||
if (f->is_using) {
|
||||
case_ast_node(p, Parameter, node);
|
||||
if (p->is_using) {
|
||||
str = gb_string_appendc(str, "using ");
|
||||
}
|
||||
gb_for_array(i, f->names) {
|
||||
AstNode *name = f->names[i];
|
||||
gb_for_array(i, p->names) {
|
||||
AstNode *name = p->names[i];
|
||||
if (i > 0)
|
||||
str = gb_string_appendc(str, ", ");
|
||||
str = write_expr_to_string(str, name);
|
||||
}
|
||||
|
||||
str = gb_string_appendc(str, ": ");
|
||||
str = write_expr_to_string(str, f->type);
|
||||
str = write_expr_to_string(str, p->type);
|
||||
case_end;
|
||||
|
||||
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);
|
||||
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, ")");
|
||||
case_end;
|
||||
|
||||
@@ -3924,19 +3961,37 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
str = gb_string_appendc(str, "struct ");
|
||||
if (st->is_packed) str = gb_string_appendc(str, "#packed ");
|
||||
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, "}");
|
||||
case_end;
|
||||
|
||||
case_ast_node(st, RawUnionType, node);
|
||||
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, "}");
|
||||
case_end;
|
||||
|
||||
case_ast_node(st, UnionType, node);
|
||||
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, "}");
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -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_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 {
|
||||
Entity *e;
|
||||
DeclInfo *d;
|
||||
};
|
||||
gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator());
|
||||
gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator());
|
||||
defer (gb_array_free(delayed_const));
|
||||
defer (gb_array_free(delayed_type));
|
||||
gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, gb_array_count(stmts));
|
||||
gbArray(Delay) delayed_type; gb_array_init_reserve(delayed_type, c->tmp_allocator, gb_array_count(stmts));
|
||||
|
||||
gb_for_array(i, stmts) {
|
||||
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
|
||||
Type *t = operand->type;
|
||||
if (is_type_untyped(t)) {
|
||||
if (t == t_invalid) {
|
||||
error(e->token, "Use of untyped thing in %.*s", LIT(context_name));
|
||||
if (t == t_invalid || is_type_untyped_nil(t)) {
|
||||
error(e->token, "Use of untyped nil in %.*s", LIT(context_name));
|
||||
e->type = t_invalid;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
gb_array_init_reserve(operands, gb_heap_allocator(), 2*lhs_count);
|
||||
defer (gb_array_free(operands));
|
||||
gb_array_init_reserve(operands, c->tmp_allocator, 2*lhs_count);
|
||||
|
||||
gb_for_array(i, inits) {
|
||||
AstNode *rhs = inits[i];
|
||||
@@ -907,10 +916,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
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;
|
||||
gb_array_init(operands, gb_heap_allocator());
|
||||
defer (gb_array_free(operands));
|
||||
gb_array_init_reserve(operands, c->tmp_allocator, 2 * gb_array_count(as->lhs));
|
||||
|
||||
gb_for_array(i, as->rhs) {
|
||||
AstNode *rhs = as->rhs[i];
|
||||
@@ -1091,8 +1103,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
AstNode *default_stmt = NULL;
|
||||
if (stmt->kind == AstNode_CaseClause) {
|
||||
ast_node(c, CaseClause, stmt);
|
||||
if (gb_array_count(c->list) == 0) {
|
||||
ast_node(cc, CaseClause, stmt);
|
||||
if (gb_array_count(cc->list) == 0) {
|
||||
default_stmt = stmt;
|
||||
}
|
||||
} else {
|
||||
@@ -1158,9 +1170,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
HashKey key = hash_exact_value(y.value);
|
||||
auto *found = map_get(&seen, key);
|
||||
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);
|
||||
TypeAndToken *taps = gb_alloc_array(gb_heap_allocator(), TypeAndToken, count);
|
||||
defer (gb_free(gb_heap_allocator(), taps));
|
||||
TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
|
||||
|
||||
multi_map_get_all(&seen, key, taps);
|
||||
b32 continue_outer = false;
|
||||
@@ -1227,8 +1241,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
AstNode *default_stmt = NULL;
|
||||
if (stmt->kind == AstNode_CaseClause) {
|
||||
ast_node(c, CaseClause, stmt);
|
||||
if (gb_array_count(c->list) == 0) {
|
||||
ast_node(cc, CaseClause, stmt);
|
||||
if (gb_array_count(cc->list) == 0) {
|
||||
default_stmt = stmt;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -22,9 +22,9 @@ enum BasicKind {
|
||||
Basic_UntypedBool,
|
||||
Basic_UntypedInteger,
|
||||
Basic_UntypedFloat,
|
||||
Basic_UntypedPointer,
|
||||
Basic_UntypedString,
|
||||
Basic_UntypedRune,
|
||||
Basic_UntypedNil,
|
||||
|
||||
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_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_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_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[] = {
|
||||
@@ -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_integer = &basic_types[Basic_UntypedInteger];
|
||||
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_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_rune = &basic_type_aliases[1];
|
||||
|
||||
@@ -548,6 +548,11 @@ b32 is_type_any(Type *t) {
|
||||
t = base_type(t);
|
||||
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) {
|
||||
@@ -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) {
|
||||
t = base_type(t);
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
return true;
|
||||
return t->kind != Basic_UntypedNil;
|
||||
case Type_Pointer:
|
||||
return true;
|
||||
case Type_Record: {
|
||||
@@ -681,12 +705,12 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
Type *default_type(Type *type) {
|
||||
if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_UntypedBool: return &basic_types[Basic_bool];
|
||||
case Basic_UntypedInteger: return &basic_types[Basic_int];
|
||||
case Basic_UntypedFloat: return &basic_types[Basic_f64];
|
||||
case Basic_UntypedString: return &basic_types[Basic_string];
|
||||
case Basic_UntypedRune: return &basic_types[Basic_rune];
|
||||
case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
|
||||
case Basic_UntypedBool: return t_bool;
|
||||
case Basic_UntypedInteger: return t_int;
|
||||
case Basic_UntypedFloat: return t_f64;
|
||||
case Basic_UntypedString: return t_string;
|
||||
case Basic_UntypedRune: return t_rune;
|
||||
// case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
|
||||
}
|
||||
}
|
||||
return type;
|
||||
@@ -952,6 +976,17 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
return gb_clamp(size, 1, s.max_align);
|
||||
} 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: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
@@ -964,6 +999,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
}
|
||||
}
|
||||
return max;
|
||||
} else if (t->Record.field_count > 0) {
|
||||
return type_align_of(s, allocator, t->Record.fields[0]->type);
|
||||
}
|
||||
break;
|
||||
case TypeRecord_Union: {
|
||||
|
||||
@@ -21,8 +21,9 @@ b32 ssa_gen_init(ssaGen *s, Checker *c) {
|
||||
// TODO(bill): generate appropriate output name
|
||||
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));
|
||||
if (err != gbFileError_None)
|
||||
if (err != gbFileError_None) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 *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));
|
||||
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, 2, t_bool_ptr), ordered);
|
||||
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, 4, t_int_ptr), align);
|
||||
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_int_ptr), align);
|
||||
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_bool_ptr), ordered);
|
||||
}
|
||||
|
||||
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 *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, 4, t_int_ptr), align);
|
||||
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_int_ptr), align);
|
||||
}
|
||||
break;
|
||||
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 *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, 4, t_int_ptr), align);
|
||||
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_int_ptr), align);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
{
|
||||
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);
|
||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
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);
|
||||
|
||||
@@ -157,13 +157,7 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
||||
case Basic_string: ssa_fprintf(f, "%%..string"); 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_any:
|
||||
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;
|
||||
case Basic_any: ssa_fprintf(f, "%%..any"); break;
|
||||
}
|
||||
break;
|
||||
case Type_Array:
|
||||
@@ -491,7 +485,8 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
|
||||
} break;
|
||||
|
||||
default:
|
||||
GB_PANIC("Invalid ExactValue: %d", value.kind);
|
||||
ssa_fprintf(f, "zeroinitializer");
|
||||
// GB_PANIC("Invalid ExactValue: %d", value.kind);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -538,6 +533,10 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
|
||||
}
|
||||
} break;
|
||||
|
||||
case ssaValue_Nil:
|
||||
ssa_fprintf(f, "zeroinitializer");
|
||||
break;
|
||||
|
||||
case ssaValue_TypeName:
|
||||
ssa_print_encoded_local(f, value->TypeName.name);
|
||||
break;
|
||||
@@ -1045,9 +1044,16 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) {
|
||||
ssa_fprintf(f, " = type {i8*, ");
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, "} ; Basic_string\n");
|
||||
|
||||
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) {
|
||||
auto *entry = &m->members.entries[member_index];
|
||||
|
||||
@@ -298,6 +298,7 @@ enum ssaValueKind {
|
||||
|
||||
ssaValue_Constant,
|
||||
ssaValue_ConstantSlice,
|
||||
ssaValue_Nil,
|
||||
ssaValue_TypeName,
|
||||
ssaValue_Global,
|
||||
ssaValue_Param,
|
||||
@@ -323,6 +324,9 @@ struct ssaValue {
|
||||
ssaValue *backing_array;
|
||||
i64 count;
|
||||
} ConstantSlice;
|
||||
struct {
|
||||
Type *type;
|
||||
} Nil;
|
||||
struct {
|
||||
String name;
|
||||
Type * type;
|
||||
@@ -540,6 +544,8 @@ Type *ssa_type(ssaValue *value) {
|
||||
return value->Constant.type;
|
||||
case ssaValue_ConstantSlice:
|
||||
return value->ConstantSlice.type;
|
||||
case ssaValue_Nil:
|
||||
return value->Nil.type;
|
||||
case ssaValue_TypeName:
|
||||
return value->TypeName.type;
|
||||
case ssaValue_Global:
|
||||
@@ -643,6 +649,12 @@ ssaValue *ssa_make_value_param(gbAllocator a, ssaProcedure *parent, Entity *e) {
|
||||
v->Param.type = e->type;
|
||||
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) {
|
||||
@@ -975,11 +987,8 @@ ssaValue *ssa_emit_comment(ssaProcedure *p, String text) {
|
||||
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
|
||||
ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
|
||||
ssaValue *zero = ssa_make_instr_zero_init(proc, instr);
|
||||
instr->Instr.parent = b;
|
||||
zero ->Instr.parent = b;
|
||||
gb_array_append(b->instrs, instr);
|
||||
gb_array_append(b->instrs, zero);
|
||||
|
||||
// if (zero_initialized) {
|
||||
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)) {
|
||||
// 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));
|
||||
} 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));
|
||||
}
|
||||
|
||||
@@ -1880,6 +1889,10 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
||||
if (is_type_any(dst)) {
|
||||
ssaValue *result = ssa_add_local_generated(proc, t_any);
|
||||
|
||||
if (is_type_untyped_nil(src)) {
|
||||
return ssa_emit_load(proc, result);
|
||||
}
|
||||
|
||||
ssaValue *data = NULL;
|
||||
if (value->kind == ssaValue_Instr &&
|
||||
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);
|
||||
}
|
||||
|
||||
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_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),
|
||||
LIT(token.pos.file), token.pos.line, token.pos.column);
|
||||
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));
|
||||
|
||||
@@ -275,6 +275,8 @@ ExactValue exact_binary_operator_value(Token op, ExactValue x, ExactValue y) {
|
||||
switch (op.kind) {
|
||||
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_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;
|
||||
}
|
||||
break;
|
||||
|
||||
170
src/parser.cpp
170
src/parser.cpp
@@ -131,7 +131,7 @@ AST_NODE_KIND(_ExprBegin, "", struct{}) \
|
||||
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
||||
AST_NODE_KIND(CallExpr, "call expression", struct { \
|
||||
AstNode *proc; \
|
||||
gbArray(AstNode *) args; \
|
||||
AstNodeArray args; \
|
||||
Token open, close; \
|
||||
Token ellipsis; \
|
||||
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(_DeclEnd, "", struct{}) \
|
||||
AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
||||
AST_NODE_KIND(Field, "field", struct { \
|
||||
AST_NODE_KIND(Parameter, "parameter", struct { \
|
||||
AstNodeArray names; \
|
||||
AstNode *type; \
|
||||
b32 is_using; \
|
||||
@@ -444,11 +444,11 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->ImportDecl.token;
|
||||
case AstNode_ForeignSystemLibrary:
|
||||
return node->ForeignSystemLibrary.token;
|
||||
case AstNode_Field: {
|
||||
if (node->Field.names)
|
||||
return ast_node_token(node->Field.names[0]);
|
||||
case AstNode_Parameter: {
|
||||
if (node->Parameter.names)
|
||||
return ast_node_token(node->Parameter.names[0]);
|
||||
else
|
||||
return ast_node_token(node->Field.type);
|
||||
return ast_node_token(node->Parameter.type);
|
||||
}
|
||||
case AstNode_ProcType:
|
||||
return node->ProcType.token;
|
||||
@@ -545,7 +545,7 @@ gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token
|
||||
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);
|
||||
result->CallExpr.proc = proc;
|
||||
result->CallExpr.args = args;
|
||||
@@ -823,11 +823,11 @@ gb_inline AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type
|
||||
return result;
|
||||
}
|
||||
|
||||
gb_inline AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
|
||||
AstNode *result = make_node(f, AstNode_Field);
|
||||
result->Field.names = names;
|
||||
result->Field.type = type;
|
||||
result->Field.is_using = is_using;
|
||||
gb_inline AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
|
||||
AstNode *result = make_node(f, AstNode_Parameter);
|
||||
result->Parameter.names = names;
|
||||
result->Parameter.type = type;
|
||||
result->Parameter.is_using = is_using;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -961,6 +961,19 @@ gb_inline Token expect_token(AstFile *f, TokenKind kind) {
|
||||
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) {
|
||||
Token prev = f->curr_token;
|
||||
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;
|
||||
} else */{
|
||||
AstNode *right = parse_binary_expr(f, false, prec+1);
|
||||
right = parse_binary_expr(f, false, prec+1);
|
||||
gbArray(AstNode *) args;
|
||||
gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
|
||||
gb_array_append(args, expression);
|
||||
@@ -1841,58 +1854,54 @@ AstNode *parse_proc_type(AstFile *f) {
|
||||
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 params = make_ast_node_array(f);
|
||||
|
||||
while (f->curr_token.kind == Token_Identifier ||
|
||||
f->curr_token.kind == Token_using) {
|
||||
AstNode *field = parse_field_decl(f);
|
||||
gb_array_append(params, field);
|
||||
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 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) {
|
||||
break;
|
||||
}
|
||||
@@ -2011,7 +2020,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
||||
b32 is_packed = false;
|
||||
b32 is_ordered = false;
|
||||
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 (is_packed) {
|
||||
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");
|
||||
}
|
||||
|
||||
Token open = expect_token(f, Token_OpenBrace);
|
||||
Token open = expect_token_after(f, Token_OpenBrace, "`struct`");
|
||||
isize decl_count = 0;
|
||||
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
|
||||
Token close = expect_token(f, Token_CloseBrace);
|
||||
@@ -2041,7 +2050,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
||||
|
||||
case 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;
|
||||
AstNodeArray decls = parse_struct_params(f, &decl_count, false);
|
||||
Token close = expect_token(f, Token_CloseBrace);
|
||||
@@ -2050,7 +2059,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
||||
}
|
||||
|
||||
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);
|
||||
isize decl_count = 0;
|
||||
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);
|
||||
|
||||
open = expect_token(f, Token_OpenBrace);
|
||||
open = expect_token_after(f, Token_OpenBrace, "`enum`");
|
||||
|
||||
while (f->curr_token.kind != Token_CloseBrace &&
|
||||
f->curr_token.kind != Token_EOF) {
|
||||
@@ -2161,7 +2170,7 @@ Token parse_procedure_signature(AstFile *f,
|
||||
Token proc_token = expect_token(f, Token_proc);
|
||||
expect_token(f, Token_OpenParen);
|
||||
*params = parse_parameter_list(f);
|
||||
expect_token(f, Token_CloseParen);
|
||||
expect_token_after(f, Token_CloseParen, "parameter list");
|
||||
*results = parse_results(f);
|
||||
return proc_token;
|
||||
}
|
||||
@@ -2210,17 +2219,17 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
|
||||
AstNodeArray values = NULL;
|
||||
AstNode *type = NULL;
|
||||
|
||||
gb_for_array(i, names) {
|
||||
AstNode *name = names[i];
|
||||
if (name->kind == AstNode_Ident) {
|
||||
String n = name->Ident.string;
|
||||
// NOTE(bill): Check for reserved identifiers
|
||||
if (n == "context") {
|
||||
syntax_error(ast_node_token(name), "`context` is a reserved identifier");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// gb_for_array(i, names) {
|
||||
// AstNode *name = names[i];
|
||||
// if (name->kind == AstNode_Ident) {
|
||||
// String n = name->Ident.string;
|
||||
// // NOTE(bill): Check for reserved identifiers
|
||||
// if (n == "context") {
|
||||
// syntax_error(ast_node_token(name), "`context` is a reserved identifier");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (allow_token(f, Token_Colon)) {
|
||||
if (!allow_token(f, Token_type)) {
|
||||
@@ -2258,8 +2267,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
|
||||
// NOTE(bill): Do not fail though
|
||||
}
|
||||
|
||||
AstNode *type = parse_type(f);
|
||||
return make_type_decl(f, token, names[0], type);
|
||||
return make_type_decl(f, token, names[0], parse_type(f));
|
||||
} else if (f->curr_token.kind == Token_proc &&
|
||||
is_mutable == false) {
|
||||
// NOTE(bill): Procedure declarations
|
||||
@@ -2434,6 +2442,7 @@ AstNode *parse_case_clause(AstFile *f) {
|
||||
expect_token(f, Token_default);
|
||||
}
|
||||
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);
|
||||
|
||||
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_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);
|
||||
|
||||
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;
|
||||
|
||||
{
|
||||
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};
|
||||
gb_array_append(p->imports, runtime_file);
|
||||
}
|
||||
|
||||
@@ -190,11 +190,11 @@ void print_ast(AstNode *node, isize indent) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AstNode_Field:
|
||||
gb_for_array(i, node->Field.names) {
|
||||
print_ast(node->Field.names[i], indent+1);
|
||||
case AstNode_Parameter:
|
||||
gb_for_array(i, node->Parameter.names) {
|
||||
print_ast(node->Parameter.names[i], indent+1);
|
||||
}
|
||||
print_ast(node->Field.type, indent);
|
||||
print_ast(node->Parameter.type, indent);
|
||||
break;
|
||||
case AstNode_PointerType:
|
||||
print_indent(indent);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user