Untyped nil

This commit is contained in:
Ginger Bill
2016-10-06 17:11:17 +01:00
parent fee504636f
commit 50301557b2
28 changed files with 8078 additions and 8567 deletions

1
.gitignore vendored
View File

@@ -254,3 +254,4 @@ paket-files/
*.sln
!misc/llvm-bim/lli.exe
!misc/llvm-bim/opt.exe
builds

View File

@@ -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%

View File

@@ -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
}
}
}

View File

@@ -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
}

View 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
}

View File

@@ -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,
}
}

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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%

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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: {

View File

@@ -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);

View File

@@ -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];

View File

@@ -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));

View File

@@ -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;

View File

@@ -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);
}

View 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