diff --git a/code/demo.odin b/code/demo.odin index 7ea6c9f28..3bd1588e6 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,6 +1,6 @@ -#import "fmt.odin"; +#import "game.odin"; main :: proc() { - fmt.println("Hellope"); + game.run(); } diff --git a/core/fmt.odin b/core/fmt.odin index 8cc2d6f16..2e6c8926f 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -43,7 +43,7 @@ printf :: proc(fmt: string, args: ..any) -> int { fprint_type :: proc(f: ^os.File, info: ^Type_Info) { data: [PRINT_BUF_SIZE]byte; buf := data[:0]; - print_type_to_buffer(^buf, info); + bprint_type(^buf, info); os.write(f, buf); } @@ -59,7 +59,7 @@ print_byte_buffer :: proc(buf: ^[]byte, b: []byte) { } } -print_string_to_buffer :: proc(buf: ^[]byte, s: string) { +bprint_string :: proc(buf: ^[]byte, s: string) { print_byte_buffer(buf, s as []byte); } @@ -71,30 +71,30 @@ byte_reverse :: proc(b: []byte) { } } -print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) { +bprint_rune :: proc(buf: ^[]byte, r: rune) { b, n := utf8.encode_rune(r); - print_string_to_buffer(buf, b[:n] as string); + bprint_string(buf, b[:n] as string); } -print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, ' '); } -print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, '\n'); } +bprint_space :: proc(buf: ^[]byte) { bprint_rune(buf, ' '); } +bprint_nl :: proc(buf: ^[]byte) { bprint_rune(buf, '\n'); } __NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"; -print_bool_to_buffer :: proc(buffer: ^[]byte, b : bool) { - if b { print_string_to_buffer(buffer, "true"); } - else { print_string_to_buffer(buffer, "false"); } +bprint_bool :: proc(buffer: ^[]byte, b : bool) { + if b { bprint_string(buffer, "true"); } + else { bprint_string(buffer, "false"); } } -print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline { - print_string_to_buffer(buffer, "0x"); - print_u64_to_buffer(buffer, p as uint as u64); +bprint_pointer :: proc(buffer: ^[]byte, p: rawptr) #inline { + bprint_string(buffer, "0x"); + bprint_u64(buffer, p as uint as u64); } -print_f16_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 4); } -print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7); } -print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f as f64, 16); } -print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) { +bprint_f16 :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 4); } +bprint_f32 :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7); } +bprint_f64 :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f as f64, 16); } +bprint_u64 :: proc(buffer: ^[]byte, value: u64) { i := value; buf: [20]byte; len := 0; @@ -108,33 +108,32 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) { i /= 10; } byte_reverse(buf[:len]); - print_string_to_buffer(buffer, buf[:len] as string); + bprint_string(buffer, buf[:len] as string); } -print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) { +bprint_i64 :: proc(buffer: ^[]byte, value: i64) { + // TODO(bill): Cleanup printing i := value; - neg := i < 0; - if neg { + if i < 0 { i = -i; - print_rune_to_buffer(buffer, '-'); + bprint_rune(buffer, '-'); } - print_u64_to_buffer(buffer, i as u64); + bprint_u64(buffer, i as u64); } -print_u128_to_buffer :: proc(buffer: ^[]byte, value: u128) { +bprint_u128 :: proc(buffer: ^[]byte, value: u128) { a := value transmute [2]u64; if a[1] != 0 { - print_u64_to_buffer(buffer, a[1]); + bprint_u64(buffer, a[1]); } - print_u64_to_buffer(buffer, a[0]); + bprint_u64(buffer, a[0]); } -print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) { +bprint_i128 :: proc(buffer: ^[]byte, value: i128) { i := value; - neg := i < 0; - if neg { + if i < 0 { i = -i; - print_rune_to_buffer(buffer, '-'); + bprint_rune(buffer, '-'); } - print_u128_to_buffer(buffer, i as u128); + bprint_u128(buffer, i as u128); } @@ -142,30 +141,30 @@ print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) { print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) { f := value; if f == 0 { - print_rune_to_buffer(buffer, '0'); + bprint_rune(buffer, '0'); return; } if f < 0 { - print_rune_to_buffer(buffer, '-'); + bprint_rune(buffer, '-'); f = -f; } i := f as u64; - print_u64_to_buffer(buffer, i); + bprint_u64(buffer, i); f -= i as f64; - print_rune_to_buffer(buffer, '.'); + bprint_rune(buffer, '.'); mult: f64 = 10.0; for ; decimal_places >= 0; decimal_places-- { i = (f * mult) as u64; - print_u64_to_buffer(buffer, i as u64); + bprint_u64(buffer, i as u64); f -= i as f64 / mult; mult *= 10; } } -print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) { +bprint_type :: proc(buf: ^[]byte, ti: ^Type_Info) { if ti == nil { return; } @@ -173,127 +172,127 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) { using Type_Info; match type info : ti { case Named: - print_string_to_buffer(buf, info.name); + bprint_string(buf, info.name); case Integer: match { case ti == type_info(int): - print_string_to_buffer(buf, "int"); + bprint_string(buf, "int"); case ti == type_info(uint): - print_string_to_buffer(buf, "uint"); + bprint_string(buf, "uint"); default: if info.signed { - print_string_to_buffer(buf, "i"); + bprint_string(buf, "i"); } else { - print_string_to_buffer(buf, "u"); + bprint_string(buf, "u"); } - print_u64_to_buffer(buf, 8*info.size as u64); + bprint_u64(buf, 8*info.size as u64); } case Float: match info.size { - case 4: print_string_to_buffer(buf, "f32"); - case 8: print_string_to_buffer(buf, "f64"); + case 4: bprint_string(buf, "f32"); + case 8: bprint_string(buf, "f64"); } - case String: print_string_to_buffer(buf, "string"); - case Boolean: print_string_to_buffer(buf, "bool"); + case String: bprint_string(buf, "string"); + case Boolean: bprint_string(buf, "bool"); case Pointer: if info.elem == nil { - print_string_to_buffer(buf, "rawptr"); + bprint_string(buf, "rawptr"); } else { - print_string_to_buffer(buf, "^"); - print_type_to_buffer(buf, info.elem); + bprint_string(buf, "^"); + bprint_type(buf, info.elem); } case Maybe: - print_string_to_buffer(buf, "?"); - print_type_to_buffer(buf, info.elem); + bprint_string(buf, "?"); + bprint_type(buf, info.elem); case Procedure: - print_string_to_buffer(buf, "proc"); + bprint_string(buf, "proc"); if info.params == nil { - print_string_to_buffer(buf, "()"); + bprint_string(buf, "()"); } else { count := (info.params as ^Tuple).fields.count; - if count == 1 { print_string_to_buffer(buf, "("); } - print_type_to_buffer(buf, info.params); - if count == 1 { print_string_to_buffer(buf, ")"); } + if count == 1 { bprint_string(buf, "("); } + bprint_type(buf, info.params); + if count == 1 { bprint_string(buf, ")"); } } if info.results != nil { - print_string_to_buffer(buf, " -> "); - print_type_to_buffer(buf, info.results); + bprint_string(buf, " -> "); + bprint_type(buf, info.results); } case Tuple: count := info.fields.count; - if count != 1 { print_string_to_buffer(buf, "("); } + if count != 1 { bprint_string(buf, "("); } for i := 0; i < count; i++ { - if i > 0 { print_string_to_buffer(buf, ", "); } + if i > 0 { bprint_string(buf, ", "); } f := info.fields[i]; if f.name.count > 0 { - print_string_to_buffer(buf, f.name); - print_string_to_buffer(buf, ": "); + bprint_string(buf, f.name); + bprint_string(buf, ": "); } - print_type_to_buffer(buf, f.type_info); + bprint_type(buf, f.type_info); } - if count != 1 { print_string_to_buffer(buf, ")"); } + if count != 1 { bprint_string(buf, ")"); } case Array: - print_string_to_buffer(buf, "["); - print_i64_to_buffer(buf, info.count as i64); - print_string_to_buffer(buf, "]"); - print_type_to_buffer(buf, info.elem); + bprint_string(buf, "["); + bprint_i64(buf, info.count as i64); + bprint_string(buf, "]"); + bprint_type(buf, info.elem); case Slice: - print_string_to_buffer(buf, "["); - print_string_to_buffer(buf, "]"); - print_type_to_buffer(buf, info.elem); + bprint_string(buf, "["); + bprint_string(buf, "]"); + bprint_type(buf, info.elem); case Vector: - print_string_to_buffer(buf, "[vector "); - print_i64_to_buffer(buf, info.count as i64); - print_string_to_buffer(buf, "]"); - print_type_to_buffer(buf, info.elem); + bprint_string(buf, "[vector "); + bprint_i64(buf, info.count as i64); + bprint_string(buf, "]"); + bprint_type(buf, info.elem); case Struct: - print_string_to_buffer(buf, "struct "); - if info.packed { print_string_to_buffer(buf, "#packed "); } - if info.ordered { print_string_to_buffer(buf, "#ordered "); } - print_string_to_buffer(buf, "{"); + bprint_string(buf, "struct "); + if info.packed { bprint_string(buf, "#packed "); } + if info.ordered { bprint_string(buf, "#ordered "); } + bprint_string(buf, "{"); for i := 0; i < info.fields.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } - print_any_to_buffer(buf, info.fields[i].name); - print_string_to_buffer(buf, ": "); - print_type_to_buffer(buf, info.fields[i].type_info); + bprint_any(buf, info.fields[i].name); + bprint_string(buf, ": "); + bprint_type(buf, info.fields[i].type_info); } - print_string_to_buffer(buf, "}"); + bprint_string(buf, "}"); case Union: - print_string_to_buffer(buf, "union {"); + bprint_string(buf, "union {"); for i := 0; i < info.fields.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } - print_any_to_buffer(buf, info.fields[i].name); - print_string_to_buffer(buf, ": "); - print_type_to_buffer(buf, info.fields[i].type_info); + bprint_any(buf, info.fields[i].name); + bprint_string(buf, ": "); + bprint_type(buf, info.fields[i].type_info); } - print_string_to_buffer(buf, "}"); + bprint_string(buf, "}"); case Raw_Union: - print_string_to_buffer(buf, "raw_union {"); + bprint_string(buf, "raw_union {"); for i := 0; i < info.fields.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } - print_any_to_buffer(buf, info.fields[i].name); - print_string_to_buffer(buf, ": "); - print_type_to_buffer(buf, info.fields[i].type_info); + bprint_any(buf, info.fields[i].name); + bprint_string(buf, ": "); + bprint_type(buf, info.fields[i].type_info); } - print_string_to_buffer(buf, "}"); + bprint_string(buf, "}"); case Enum: - print_string_to_buffer(buf, "enum "); - print_type_to_buffer(buf, info.base); - print_string_to_buffer(buf, "{}"); + bprint_string(buf, "enum "); + bprint_type(buf, info.base); + bprint_string(buf, "{}"); } } @@ -305,14 +304,14 @@ make_any :: proc(type_info: ^Type_Info, data: rawptr) -> any { return a; } -print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { +bprint_any :: proc(buf: ^[]byte, arg: any) { if arg.type_info == nil { - print_string_to_buffer(buf, ""); + bprint_string(buf, ""); return; } if arg.data == nil { - print_string_to_buffer(buf, ""); + bprint_string(buf, ""); return; } @@ -322,73 +321,73 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { a := make_any(info.base, arg.data); match type b : info.base { case Struct: - print_string_to_buffer(buf, info.name); - print_string_to_buffer(buf, "{"); + bprint_string(buf, info.name); + bprint_string(buf, "{"); for i := 0; i < b.fields.count; i++ { f := b.fields[i]; if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } - print_string_to_buffer(buf, f.name); - // print_any_to_buffer(buf, f.offset); - print_string_to_buffer(buf, " = "); + bprint_string(buf, f.name); + // bprint_any(buf, f.offset); + bprint_string(buf, " = "); data := arg.data as ^byte + f.offset; - print_any_to_buffer(buf, make_any(f.type_info, data)); + bprint_any(buf, make_any(f.type_info, data)); } - print_string_to_buffer(buf, "}"); + bprint_string(buf, "}"); default: - print_any_to_buffer(buf, a); + bprint_any(buf, a); } case Integer: match type i : arg { - case i8: print_i64_to_buffer(buf, i as i64); - case u8: print_u64_to_buffer(buf, i as u64); - case i16: print_i64_to_buffer(buf, i as i64); - case u16: print_u64_to_buffer(buf, i as u64); - case i32: print_i64_to_buffer(buf, i as i64); - case u32: print_u64_to_buffer(buf, i as u64); - case i64: print_i64_to_buffer(buf, i as i64); - case u64: print_u64_to_buffer(buf, i as u64); - case i128: print_i128_to_buffer(buf, i); - case u128: print_u128_to_buffer(buf, i); + case i8: bprint_i64(buf, i as i64); + case u8: bprint_u64(buf, i as u64); + case i16: bprint_i64(buf, i as i64); + case u16: bprint_u64(buf, i as u64); + case i32: bprint_i64(buf, i as i64); + case u32: bprint_u64(buf, i as u64); + case i64: bprint_i64(buf, i); + case u64: bprint_u64(buf, i); + case i128: bprint_i128(buf, i); + case u128: bprint_u128(buf, i); - case int: print_u64_to_buffer(buf, i as u64); - case uint: print_u64_to_buffer(buf, i as u64); + case int: bprint_i64(buf, i as i64); + case uint: bprint_u64(buf, i as u64); } case Float: match type f : arg { - // case f16: print_f64_to_buffer(buf, f as f64); - case f32: print_f32_to_buffer(buf, f); - case f64: print_f64_to_buffer(buf, f); - // case f128: print_f64_to_buffer(buf, f as f64); + // case f16: bprint_f64(buf, f as f64); + case f32: bprint_f32(buf, f); + case f64: bprint_f64(buf, f); + // case f128: bprint_f64(buf, f as f64); } case String: match type s : arg { - case string: print_string_to_buffer(buf, s); + case string: bprint_string(buf, s); } case Boolean: match type b : arg { - case bool: print_bool_to_buffer(buf, b); + case bool: bprint_bool(buf, b); } case Pointer: match type p : arg { - case ^Type_Info: print_type_to_buffer(buf, p); - default: print_pointer_to_buffer(buf, (arg.data as ^rawptr)^); + case ^Type_Info: bprint_type(buf, p); + default: bprint_pointer(buf, (arg.data as ^rawptr)^); } case Maybe: size := mem.size_of_type_info(info.elem); data := slice_ptr(arg.data as ^byte, size+1); if data[size] != 0 { - print_any_to_buffer(buf, make_any(info.elem, arg.data)); + bprint_any(buf, make_any(info.elem, arg.data)); } else { - print_string_to_buffer(buf, "nil"); + bprint_string(buf, "nil"); } case Enum: @@ -404,33 +403,33 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { case u32: value = i as i64; case u64: value = i as i64; } - print_string_to_buffer(buf, __enum_to_string(arg.type_info, value)); + bprint_string(buf, __enum_to_string(arg.type_info, value)); case Array: bprintf(buf, "[%]%{", info.count, info.elem); - defer print_string_to_buffer(buf, "}"); + defer bprint_string(buf, "}"); for i := 0; i < info.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } data := arg.data as ^byte + i*info.elem_size; - print_any_to_buffer(buf, make_any(info.elem, data)); + bprint_any(buf, make_any(info.elem, data)); } case Slice: slice := arg.data as ^[]byte; bprintf(buf, "[]%{", info.elem); - defer print_string_to_buffer(buf, "}"); + defer bprint_string(buf, "}"); for i := 0; i < slice.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } data := slice.data + i*info.elem_size; - print_any_to_buffer(buf, make_any(info.elem, data)); + bprint_any(buf, make_any(info.elem, data)); } case Vector: @@ -445,7 +444,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { } bprintf(buf, "[vector %]%{", info.count, info.elem); - defer print_string_to_buffer(buf, "}"); + defer bprint_string(buf, "}"); if is_bool(info.elem) { return; @@ -453,37 +452,37 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { for i := 0; i < info.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } data := arg.data as ^byte + i*info.elem_size; - print_any_to_buffer(buf, make_any(info.elem, data)); + bprint_any(buf, make_any(info.elem, data)); } case Struct: bprintf(buf, "%{", arg.type_info); - defer print_string_to_buffer(buf, "}"); + defer bprint_string(buf, "}"); for i := 0; i < info.fields.count; i++ { if i > 0 { - print_string_to_buffer(buf, ", "); + bprint_string(buf, ", "); } - print_string_to_buffer(buf, info.fields[i].name); - print_string_to_buffer(buf, " = "); + bprint_string(buf, info.fields[i].name); + bprint_string(buf, " = "); data := arg.data as ^byte + info.fields[i].offset; ti := info.fields[i].type_info; - print_any_to_buffer(buf, make_any(ti, data)); + bprint_any(buf, make_any(ti, data)); } case Union: - print_string_to_buffer(buf, "(union)"); + bprint_string(buf, "(union)"); case Raw_Union: - print_string_to_buffer(buf, "(raw_union)"); + bprint_string(buf, "(raw_union)"); case Procedure: - print_type_to_buffer(buf, arg.type_info); - print_string_to_buffer(buf, " @ 0x"); - print_pointer_to_buffer(buf, (arg.data as ^rawptr)^); + bprint_type(buf, arg.type_info); + bprint_string(buf, " @ 0x"); + bprint_pointer(buf, (arg.data as ^rawptr)^); } } @@ -520,13 +519,13 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int { continue; } - print_string_to_buffer(buf, fmt[prev:i]); + bprint_string(buf, fmt[prev:i]); i++; // Skip % if i < fmt.count { next := fmt[i] as rune; if next == '%' { - print_string_to_buffer(buf, "%"); + bprint_string(buf, "%"); i++; prev = i; continue; @@ -538,17 +537,17 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int { } if 0 <= index && index < args.count { - print_any_to_buffer(buf, args[index]); + bprint_any(buf, args[index]); implicit_index = index+1; } else { // TODO(bill): Error check index out bounds - print_string_to_buffer(buf, ""); + bprint_string(buf, ""); } prev = i; } - print_string_to_buffer(buf, fmt[prev:]); + bprint_string(buf, fmt[prev:]); return buf.count; } @@ -573,9 +572,9 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int { arg := args[i]; is_string := arg.data != nil && is_type_string(arg.type_info); if i > 0 && !is_string && !prev_string { - print_space_to_buffer(buf); + bprint_space(buf); } - print_any_to_buffer(buf, arg); + bprint_any(buf, arg); prev_string = is_string; } return buf.count; @@ -586,8 +585,8 @@ bprintln :: proc(buf: ^[]byte, args: ..any) -> int { if i > 0 { append(buf, ' '); } - print_any_to_buffer(buf, args[i]); + bprint_any(buf, args[i]); } - print_nl_to_buffer(buf); + bprint_nl(buf); return buf.count; } diff --git a/src/build.c b/src/build.c new file mode 100644 index 000000000..84d3c26d6 --- /dev/null +++ b/src/build.c @@ -0,0 +1,83 @@ +typedef struct BuildContext { + String ODIN_OS; // target operating system + String ODIN_ARCH; // target architecture + String ODIN_VENDOR; // compiler vendor + String ODIN_VERSION; // compiler version + String ODIN_ROOT; // Odin ROOT + + i64 word_size; + i64 max_align; + String llc_flags; + String link_flags; +} BuildContext; + +String odin_root_dir(void) { + String path = global_module_path; + Array(wchar_t) path_buf; + isize len, i; + gbTempArenaMemory tmp; + wchar_t *text; + + if (global_module_path_set) { + return global_module_path; + } + + array_init_count(&path_buf, heap_allocator(), 300); + + len = 0; + for (;;) { + len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count); + if (len == 0) { + return make_string(NULL, 0); + } + if (len < path_buf.count) { + break; + } + array_resize(&path_buf, 2*path_buf.count + 300); + } + + tmp = gb_temp_arena_memory_begin(&string_buffer_arena); + + text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1); + + GetModuleFileNameW(NULL, text, len); + path = string16_to_string(heap_allocator(), make_string16(text, len)); + for (i = path.len-1; i >= 0; i--) { + u8 c = path.text[i]; + if (c == '/' || c == '\\') { + break; + } + path.len--; + } + + global_module_path = path; + global_module_path_set = true; + + gb_temp_arena_memory_end(tmp); + + array_free(&path_buf); + + return path; +} + + +void init_build_context(BuildContext *bc) { + bc->ODIN_OS = str_lit("windows"); + bc->ODIN_ARCH = str_lit("amd64"); + bc->ODIN_VENDOR = str_lit("odin"); + bc->ODIN_VERSION = str_lit("0.0.3d"); + bc->ODIN_ROOT = odin_root_dir(); + + + if (str_eq(bc->ODIN_ARCH, str_lit("amd64"))) { + bc->word_size = 8; + bc->max_align = 16; + bc->llc_flags = str_lit("-march=x86-64 "); + bc->link_flags = str_lit("/machine:x64 "); + } else if (str_eq(bc->ODIN_ARCH, str_lit("x86"))) { + bc->word_size = 4; + bc->max_align = 8; + bc->llc_flags = str_lit("-march=x86 "); + bc->link_flags = str_lit("/machine:x86 "); + } +} diff --git a/src/checker/checker.c b/src/checker/checker.c index ebdcbc722..3b1716bfa 100644 --- a/src/checker/checker.c +++ b/src/checker/checker.c @@ -535,7 +535,7 @@ void add_global_string_constant(gbAllocator a, String name, String value) { } -void init_universal_scope(void) { +void init_universal_scope(BuildContext *bc) { // NOTE(bill): No need to free these gbAllocator a = heap_allocator(); universal_scope = make_scope(NULL, a); @@ -555,11 +555,11 @@ void init_universal_scope(void) { add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil)); // TODO(bill): Set through flags in the compiler - add_global_string_constant(a, str_lit("ODIN_OS"), str_lit("windows")); - add_global_string_constant(a, str_lit("ODIN_ARCH"), str_lit("amd64")); - add_global_string_constant(a, str_lit("ODIN_VENDOR"), str_lit("odin")); - add_global_string_constant(a, str_lit("ODIN_VERSION"), str_lit(VERSION_STRING)); - add_global_string_constant(a, str_lit("ODIN_ENDIAN"), str_lit("little")); + add_global_string_constant(a, str_lit("ODIN_OS"), bc->ODIN_OS); + add_global_string_constant(a, str_lit("ODIN_ARCH"), bc->ODIN_ARCH); + add_global_string_constant(a, str_lit("ODIN_VENDOR"), bc->ODIN_VENDOR); + add_global_string_constant(a, str_lit("ODIN_VERSION"), bc->ODIN_VERSION); + add_global_string_constant(a, str_lit("ODIN_ROOT"), bc->ODIN_ROOT); // Builtin Procedures @@ -607,12 +607,13 @@ void destroy_checker_info(CheckerInfo *i) { } -void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) { +void init_checker(Checker *c, Parser *parser, BuildContext *bc) { gbAllocator a = heap_allocator(); c->parser = parser; init_checker_info(&c->info); - c->sizes = sizes; + c->sizes.word_size = bc->word_size; + c->sizes.max_align = bc->max_align; array_init(&c->proc_stack, a); array_init(&c->procs, a); @@ -698,7 +699,10 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode if (mode == Addressing_Constant) { if (is_type_constant_type(type)) { - GB_ASSERT(value.kind != ExactValue_Invalid); + // if (value.kind == ExactValue_Invalid) { + // TODO(bill): Is this correct? + // return; + // } if (!(type != t_invalid || is_type_constant_type(type))) { compiler_error("add_type_and_value - invalid type: %s", type_to_string(type)); } @@ -1086,6 +1090,35 @@ void check_global_entities_by_kind(Checker *c, EntityKind kind) { } } + + +void check_all_global_entities(Checker *c) { + for_array(i, c->info.entities.entries) { + MapDeclInfoEntry *entry = &c->info.entities.entries.e[i]; + Entity *e = cast(Entity *)cast(uintptr)entry->key.key; + DeclInfo *d = entry->value; + + if (d->scope != e->scope) { + continue; + } + + add_curr_ast_file(c, d->scope->file); + if (e->kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) { + if (e->scope->is_init) { + error(e->token, "`main` is reserved as the entry point procedure in the initial scope"); + continue; + } + } else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) { + error(e->token, "`main` is reserved as the entry point procedure in the initial scope"); + continue; + } + + Scope *prev_scope = c->context.scope; + c->context.scope = d->scope; + check_entity_decl(c, e, d, NULL, NULL); + } +} + void check_global_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray nodes, MapScope *file_scopes) { for_array(decl_index, nodes) { AstNode *decl = nodes.e[decl_index]; @@ -1120,6 +1153,9 @@ void check_global_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray AstNode *name = cd->names.e[i]; AstNode *value = cd->values.e[i]; ExactValue v = {ExactValue_Invalid}; + if (name->kind != AstNode_Ident) { + error_node(name, "A declaration's name but be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + } Entity *e = make_entity_constant(c->allocator, parent_scope, name->Ident, NULL, v); e->identifier = name; DeclInfo *di = make_declaration_info(c->allocator, parent_scope); @@ -1161,6 +1197,9 @@ void check_global_collect_entities(Checker *c, Scope *parent_scope, AstNodeArray if (i < vd->values.count) { value = vd->values.e[i]; } + if (name->kind != AstNode_Ident) { + error_node(name, "A declaration's name but be an identifier, got %.*s", LIT(ast_node_strings[name->kind])); + } Entity *e = make_entity_variable(c->allocator, parent_scope, name->Ident, NULL); e->identifier = name; entities[entity_index++] = e; @@ -1386,13 +1425,18 @@ void check_parsed_files(Checker *c) { check_import_entities(c, &file_scopes); +#if 0 check_global_entities_by_kind(c, Entity_TypeName); + check_global_entities_by_kind(c, Entity_Constant); init_preload_types(c); add_implicit_value(c, ImplicitValue_context, str_lit("context"), str_lit("__context"), t_context); - check_global_entities_by_kind(c, Entity_Constant); check_global_entities_by_kind(c, Entity_Procedure); check_global_entities_by_kind(c, Entity_Variable); - +#else + check_all_global_entities(c); + init_preload_types(c); + add_implicit_value(c, ImplicitValue_context, str_lit("context"), str_lit("__context"), t_context); +#endif for (isize i = 1; i < ImplicitValue_Count; i++) { // NOTE(bill): First is invalid diff --git a/src/checker/decl.c b/src/checker/decl.c index f418e86ce..ef227e610 100644 --- a/src/checker/decl.c +++ b/src/checker/decl.c @@ -121,10 +121,12 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc } } +#if 0 if (e->kind == Entity_Procedure) { check_proc_decl(c, e, d); return; } +#endif CheckerContext prev = c->context; c->context.scope = d->scope; c->context.decl = d; @@ -139,6 +141,11 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc case Entity_TypeName: check_type_decl(c, e, d->type_expr, named_type, cycle_checker); break; +#if 1 + case Entity_Procedure: + check_proc_decl(c, e, d); + break; +#endif } c->context = prev; @@ -279,6 +286,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e Operand operand = {0}; if (init_expr) { + // check_expr_or_type(c, &operand, init_expr); check_expr(c, &operand, init_expr); } check_init_constant(c, e, &operand); diff --git a/src/checker/expr.c b/src/checker/expr.c index f4ec7c093..d93ae762d 100644 --- a/src/checker/expr.c +++ b/src/checker/expr.c @@ -1060,7 +1060,9 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl return; } o->value = e->Constant.value; - GB_ASSERT(o->value.kind != ExactValue_Invalid); + if (o->value.kind == ExactValue_Invalid) { + return; + } o->mode = Addressing_Constant; break; diff --git a/src/common.c b/src/common.c index 2d4600b89..8c04db896 100644 --- a/src/common.c +++ b/src/common.c @@ -13,55 +13,6 @@ gb_global String global_module_path = {0}; gb_global bool global_module_path_set = false; -String get_module_dir() { - String path = global_module_path; - Array(wchar_t) path_buf; - isize len, i; - gbTempArenaMemory tmp; - wchar_t *text; - - if (global_module_path_set) { - return global_module_path; - } - - array_init_count(&path_buf, heap_allocator(), 300); - - len = 0; - for (;;) { - len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count); - if (len == 0) { - return make_string(NULL, 0); - } - if (len < path_buf.count) { - break; - } - array_resize(&path_buf, 2*path_buf.count + 300); - } - - tmp = gb_temp_arena_memory_begin(&string_buffer_arena); - - text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1); - - GetModuleFileNameW(NULL, text, len); - path = string16_to_string(heap_allocator(), make_string16(text, len)); - for (i = path.len-1; i >= 0; i--) { - u8 c = path.text[i]; - if (c == '/' || c == '\\') { - break; - } - path.len--; - } - - global_module_path = path; - global_module_path_set = true; - - gb_temp_arena_memory_end(tmp); - - array_free(&path_buf); - - return path; -} - String path_to_fullpath(gbAllocator a, String s) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena); String16 string16 = string_to_string16(string_buffer_allocator, s); diff --git a/src/exact_value.c b/src/exact_value.c index 5167e76d9..46184bb72 100644 --- a/src/exact_value.c +++ b/src/exact_value.c @@ -306,6 +306,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y) case Token_Shr: c = a >> b; break; default: goto error; } + return make_exact_value_integer(c); } break; diff --git a/src/main.c b/src/main.c index 3e45df714..e173a2794 100644 --- a/src/main.c +++ b/src/main.c @@ -1,11 +1,11 @@ #if defined(__cplusplus) extern "C" { #endif -#define VERSION_STRING "v0.0.3d" #include "common.c" #include "timings.c" #include "unicode.c" +#include "build.c" #include "tokenizer.c" #include "parser.c" // #include "printer.c" @@ -59,39 +59,6 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) { return exit_code; } -typedef enum ArchKind { - ArchKind_x64, - ArchKind_x86, -} ArchKind; - -typedef struct ArchData { - BaseTypeSizes sizes; - String llc_flags; - String link_flags; -} ArchData; - -ArchData make_arch_data(ArchKind kind) { - ArchData data = {0}; - - switch (kind) { - case ArchKind_x64: - default: - data.sizes.word_size = 8; - data.sizes.max_align = 16; - data.llc_flags = str_lit("-march=x86-64 "); - data.link_flags = str_lit("/machine:x64 "); - break; - - case ArchKind_x86: - data.sizes.word_size = 4; - data.sizes.max_align = 8; - data.llc_flags = str_lit("-march=x86 "); - data.link_flags = str_lit("/machine:x86 "); - break; - } - - return data; -} void usage(char *argv0) { gb_printf_err("%s is a tool for managing Odin source code\n", argv0); @@ -118,9 +85,10 @@ int main(int argc, char **argv) { init_string_buffer_memory(); init_global_error_collector(); - String module_dir = get_module_dir(); + BuildContext build_context = {0}; + init_build_context(&build_context); - init_universal_scope(); + init_universal_scope(&build_context); char *init_filename = NULL; bool run_output = false; @@ -131,7 +99,7 @@ int main(int argc, char **argv) { } else if (str_eq(arg1, str_lit("build"))) { init_filename = argv[2]; } else if (str_eq(arg1, str_lit("version"))) { - gb_printf("%s version %s", argv[0], VERSION_STRING); + gb_printf("%s version %.*s", argv[0], LIT(build_context.ODIN_VERSION)); return 0; } else { usage(argv[0]); @@ -157,9 +125,8 @@ int main(int argc, char **argv) { timings_start_section(&timings, str_lit("type check")); Checker checker = {0}; - ArchData arch_data = make_arch_data(ArchKind_x64); - init_checker(&checker, &parser, arch_data.sizes); + init_checker(&checker, &parser, &build_context); // defer (destroy_checker(&checker)); check_parsed_files(&checker); @@ -206,7 +173,7 @@ int main(int argc, char **argv) { // "-dce " // "-S " "", - LIT(module_dir), + LIT(build_context.ODIN_ROOT), output_name, LIT(output)); if (exit_code != 0) { return exit_code; @@ -220,10 +187,10 @@ int main(int argc, char **argv) { "%.*s " // "-debug-pass=Arguments " "", - LIT(module_dir), + LIT(build_context.ODIN_ROOT), LIT(output), optimization_level, - LIT(arch_data.llc_flags)); + LIT(build_context.llc_flags)); if (exit_code != 0) { return exit_code; } @@ -247,7 +214,7 @@ int main(int argc, char **argv) { " %.*s " "", LIT(output), LIT(output), - lib_str, LIT(arch_data.link_flags)); + lib_str, LIT(build_context.link_flags)); if (exit_code != 0) { return exit_code; } diff --git a/src/parser.c b/src/parser.c index 855dd3f2a..d224545f3 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1169,11 +1169,13 @@ bool expect_semicolon_after_stmt(AstFile *f, AstNode *s) { // return true; // } - // switch (f->curr_token.kind) { - // case Token_EOF: - // case Token_CloseBrace: - // return true; - // } + if (f->curr_token.pos.line == f->prev_token.pos.line) { + switch (f->curr_token.kind) { + case Token_EOF: + case Token_CloseBrace: + return true; + } + } if (s != NULL) { syntax_error(f->prev_token, "Expected `;` after %.*s, got `%.*s`", @@ -1194,18 +1196,18 @@ AstNode * parse_body(AstFile *f); AstNode *parse_identifier(AstFile *f) { Token token = f->curr_token; - if (token.kind == Token_Identifier) { + if (token.kind == Token_Ident) { next_token(f); } else { token.string = str_lit("_"); - expect_token(f, Token_Identifier); + expect_token(f, Token_Ident); } return make_ident(f, token); } AstNode *parse_tag_expr(AstFile *f, AstNode *expression) { Token token = expect_token(f, Token_Hash); - Token name = expect_token(f, Token_Identifier); + Token name = expect_token(f, Token_Ident); return make_tag_expr(f, token, name, expression); } @@ -1401,7 +1403,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n AstNode *parse_operand(AstFile *f, bool lhs) { AstNode *operand = NULL; // Operand switch (f->curr_token.kind) { - case Token_Identifier: + case Token_Ident: operand = parse_identifier(f); if (!lhs) { // TODO(bill): Handle? @@ -1456,7 +1458,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { case Token_Hash: { Token token = expect_token(f, Token_Hash); - Token name = expect_token(f, Token_Identifier); + Token name = expect_token(f, Token_Ident); if (str_eq(name.string, str_lit("file"))) { Token token = name; token.kind = Token_String; @@ -1584,21 +1586,15 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { bool loop = true; while (loop) { switch (f->curr_token.kind) { - case Token_OpenParen: { - if (lhs) { - // TODO(bill): Handle this shit! Is this even allowed in this language?! - } + case Token_OpenParen: operand = parse_call_expr(f, operand); - } break; + break; case Token_Period: { Token token = f->curr_token; next_token(f); - if (lhs) { - // TODO(bill): handle this - } switch (f->curr_token.kind) { - case Token_Identifier: + case Token_Ident: operand = make_selector_expr(f, token, operand, parse_identifier(f)); break; default: { @@ -1664,20 +1660,13 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { operand = make_demaybe_expr(f, operand, expect_token(f, Token_Maybe)); break; - case Token_OpenBrace: { + case Token_OpenBrace: if (!lhs && is_literal_type(operand) && f->expr_level >= 0) { - if (f->curr_token.pos.line == f->prev_token.pos.line) { - // TODO(bill): This is a hack due to optional semicolons - // TODO(bill): It's probably much better to solve this by changing - // the syntax for struct literals and array literals - operand = parse_literal_value(f, operand); - } else { - loop = false; - } + operand = parse_literal_value(f, operand); } else { loop = false; } - } break; + break; default: loop = false; @@ -1933,14 +1922,13 @@ AstNode *parse_type(AstFile *f) { } -Token parse_procedure_signature(AstFile *f, - AstNodeArray *params, AstNodeArray *results); +Token parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results); AstNode *parse_proc_type(AstFile *f) { AstNodeArray params = {0}; AstNodeArray results = {0}; - Token proc_token = parse_procedure_signature(f, ¶ms, &results); + Token proc_token = parse_proc_signature(f, ¶ms, &results); return make_proc_type(f, proc_token, params, results); } @@ -1949,7 +1937,7 @@ AstNode *parse_proc_type(AstFile *f) { AstNodeArray parse_parameter_list(AstFile *f) { AstNodeArray params = make_ast_node_array(f); - while (f->curr_token.kind == Token_Identifier || + while (f->curr_token.kind == Token_Ident || f->curr_token.kind == Token_using) { bool is_using = false; if (allow_token(f, Token_using)) { @@ -2068,7 +2056,7 @@ AstNodeArray parse_record_params(AstFile *f, isize *decl_count_, bool using_allo AstNode *parse_identifier_or_type(AstFile *f, u32 flags) { switch (f->curr_token.kind) { - case Token_Identifier: { + case Token_Ident: { AstNode *e = parse_identifier(f); while (f->curr_token.kind == Token_Period) { Token token = f->curr_token; @@ -2128,7 +2116,7 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) { bool is_packed = false; bool is_ordered = false; while (allow_token(f, Token_Hash)) { - Token tag = expect_token_after(f, Token_Identifier, "`#`"); + Token tag = expect_token_after(f, Token_Ident, "`#`"); if (str_eq(tag.string, str_lit("packed"))) { if (is_packed) { syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); @@ -2268,9 +2256,9 @@ AstNodeArray parse_results(AstFile *f) { return results; } -Token parse_procedure_signature(AstFile *f, - AstNodeArray *params, - AstNodeArray *results) { +Token parse_proc_signature(AstFile *f, + AstNodeArray *params, + AstNodeArray *results) { Token proc_token = expect_token(f, Token_proc); expect_token(f, Token_OpenParen); *params = parse_parameter_list(f); @@ -2292,11 +2280,7 @@ AstNode *parse_body(AstFile *f) { AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { - AstNodeArray params = {0}; - AstNodeArray results = {0}; - - parse_procedure_signature(f, ¶ms, &results); - AstNode *proc_type = make_proc_type(f, proc_token, params, results); + AstNode *proc_type = parse_proc_type(f); AstNode *body = NULL; u64 tags = 0; @@ -2736,7 +2720,7 @@ AstNode *parse_stmt(AstFile *f) { Token token = f->curr_token; switch (token.kind) { // Operands - case Token_Identifier: + case Token_Ident: case Token_Integer: case Token_Float: case Token_Rune: @@ -2827,7 +2811,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_Hash: { AstNode *s = NULL; Token hash_token = expect_token(f, Token_Hash); - Token name = expect_token(f, Token_Identifier); + Token name = expect_token(f, Token_Ident); String tag = name.string; if (str_eq(tag, str_lit("shared_global_scope"))) { if (f->curr_proc == NULL) { @@ -2878,10 +2862,10 @@ AstNode *parse_stmt(AstFile *f) { switch (f->curr_token.kind) { case Token_Period: import_name = f->curr_token; - import_name.kind = Token_Identifier; + import_name.kind = Token_Ident; next_token(f); break; - case Token_Identifier: + case Token_Ident: import_name = f->curr_token; next_token(f); break; @@ -3100,7 +3084,7 @@ String get_fullpath_relative(gbAllocator a, String base_dir, String path) { } String get_fullpath_core(gbAllocator a, String path) { - String module_dir = get_module_dir(); + String module_dir = odin_root_dir(); String res = {0}; char core[] = "core/"; diff --git a/src/ssa.c b/src/ssa.c index c7dd8eb84..4763a9f62 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -5300,7 +5300,7 @@ void ssa_gen_tree(ssaGen *s) { { - Token token = {Token_Identifier}; + Token token = {Token_Ident}; i32 id = cast(i32)entry_index; char name_base[] = "__$enum_values"; isize name_len = gb_size_of(name_base) + 10; @@ -5314,7 +5314,7 @@ void ssa_gen_tree(ssaGen *s) { map_ssa_value_set(&m->members, hash_string(token.string), value_array); } { - Token token = {Token_Identifier}; + Token token = {Token_Ident}; i32 id = cast(i32)entry_index; char name_base[] = "__$enum_names"; isize name_len = gb_size_of(name_base) + 10; diff --git a/src/ssa_print.c b/src/ssa_print.c index 1425e07e7..d1df0ed6c 100644 --- a/src/ssa_print.c +++ b/src/ssa_print.c @@ -1001,8 +1001,11 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) { default: { if (!is_type_float(elem_type)) { - if (is_type_unsigned(elem_type)) ssa_fprintf(f, "u"); - else ssa_fprintf(f, "s"); + if (is_type_unsigned(elem_type)) { + ssa_fprintf(f, "u"); + } else { + ssa_fprintf(f, "s"); + } } switch (bo->op) { diff --git a/src/tokenizer.c b/src/tokenizer.c index 3c30a5b38..455d7bf36 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -4,7 +4,7 @@ TOKEN_KIND(Token_Comment, "Comment"), \ \ TOKEN_KIND(Token__LiteralBegin, "_LiteralBegin"), \ - TOKEN_KIND(Token_Identifier, "Identifier"), \ + TOKEN_KIND(Token_Ident, "Identifier"), \ TOKEN_KIND(Token_Integer, "Integer"), \ TOKEN_KIND(Token_Float, "Float"), \ TOKEN_KIND(Token_Rune, "Rune"), \ @@ -157,10 +157,10 @@ typedef struct Token { } Token; Token empty_token = {Token_Invalid}; -Token blank_token = {Token_Identifier, {cast(u8 *)"_", 1}}; +Token blank_token = {Token_Ident, {cast(u8 *)"_", 1}}; Token make_token_ident(String s) { - Token t = {Token_Identifier, s}; + Token t = {Token_Ident, s}; return t; } @@ -311,8 +311,9 @@ typedef struct Tokenizer { void tokenizer_err(Tokenizer *t, char *msg, ...) { va_list va; isize column = t->read_curr - t->line+1; - if (column < 1) + if (column < 1) { column = 1; + } gb_printf_err("%.*s(%td:%td) Syntax error: ", LIT(t->fullpath), t->line_count, column); @@ -628,7 +629,7 @@ Token tokenizer_get_token(Tokenizer *t) { curr_rune = t->curr_rune; if (rune_is_letter(curr_rune)) { - token.kind = Token_Identifier; + token.kind = Token_Ident; while (rune_is_letter(t->curr_rune) || rune_is_digit(t->curr_rune)) { advance_to_next_rune(t); }