diff --git a/code/demo.odin b/code/demo.odin index 6a1a9396a..64af72d26 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,9 +1,6 @@ #load "basic.odin" main :: proc() { - str := "Hellope" - - println(str, true, 6.28) - - println([4]int{1, 2, 3, 4}) + println("% % % %", "Hellope", true, 6.28, [4]int{1, 2, 3, 4}) + println("%0 %1 %0", "Hellope", 34) } diff --git a/code/file.odin b/code/file.odin index 7ee8770e0..dc97e909e 100644 --- a/code/file.odin +++ b/code/file.odin @@ -41,18 +41,18 @@ File_Standard :: type enum { COUNT, } -__std_file_set := false; -__std_files: [File_Standard.COUNT as int]File; + +__std_files := __set_file_standards(); + +__set_file_standards :: proc() -> [File_Standard.COUNT as int]File { + return [File_Standard.COUNT as int]File{ + File{handle = GetStdHandle(STD_INPUT_HANDLE)}, + File{handle = GetStdHandle(STD_OUTPUT_HANDLE)}, + File{handle = GetStdHandle(STD_ERROR_HANDLE)}, + } +} file_get_standard :: proc(std: File_Standard) -> ^File { - // using File_Standard; - if (!__std_file_set) { - using File_Standard - __std_files[INPUT] .handle = GetStdHandle(STD_INPUT_HANDLE) - __std_files[OUTPUT].handle = GetStdHandle(STD_OUTPUT_HANDLE) - __std_files[ERROR] .handle = GetStdHandle(STD_ERROR_HANDLE) - __std_file_set = true - } return ^__std_files[std] } diff --git a/code/print.odin b/code/print.odin index 41121dbae..2a32f3c9e 100644 --- a/code/print.odin +++ b/code/print.odin @@ -2,7 +2,7 @@ #load "win32.odin" #load "file.odin" -print_string_to_buffer :: proc(buf: ^[]byte, s: string) { +print_byte_buffer :: proc(buf: ^[]byte, b: []byte) { // NOTE(bill): This is quite a hack // TODO(bill): Should I allow the raw editing of a slice by exposing its // internal members? @@ -14,13 +14,20 @@ print_string_to_buffer :: proc(buf: ^[]byte, s: string) { slice := buf as ^Raw_Bytes if slice.len < slice.cap { - n := min(slice.cap-slice.len, len(s)) - offset := ptr_offset(slice.data, slice.len) - memory_copy(offset, ^s[0], n) - slice.len += n + n := min(slice.cap-slice.len, len(b)) + if n > 0 { + offset := ptr_offset(slice.data, slice.len) + memory_copy(offset, ^b[0], n) + slice.len += n + } } } +print_string_to_buffer :: proc(buf: ^[]byte, s: string) { + print_byte_buffer(buf, s as []byte) +} + + byte_reverse :: proc(b: []byte) { n := len(b) for i := 0; i < n/2; i++ { @@ -357,43 +364,100 @@ type_info_is_string :: proc(info: ^Type_Info) -> bool { return false } -print_to_buffer :: proc(buf: ^[]byte, args: ..any) { - prev_string := false - for i := 0; i < len(args); i++ { - arg := args[i] - is_string := arg.data != null && type_info_is_string(arg.type_info) - if i > 0 && !is_string && !prev_string { - // Add space between two non-string arguments - print_space_to_buffer(buf) - } - print_any_to_buffer(buf, arg) - prev_string = is_string + +print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) { + is_digit :: proc(r: rune) -> bool #inline { + return r >= #rune "0" && r <= #rune "9" } -} -println_to_buffer :: proc(buf: ^[]byte, args: ..any) { - for i := 0; i < len(args); i++ { - arg := args[i] - if i > 0 { - print_space_to_buffer(buf) + parse_int :: proc(s: string, offset: int) -> (int, int) { + result := 0 + + for ; offset < len(s); offset++ { + c := s[offset] as rune + if !is_digit(c) { + break + } + + result *= 10 + result += (c - #rune "0") as int } - print_any_to_buffer(buf, arg) + + return result, offset } - print_nl_to_buffer(buf) + + prev := 0 + implicit_index := 0 + + for i := 0; i < len(fmt); i++ { + r := fmt[i] as rune + + if r != #rune "%" { + continue + } + + print_string_to_buffer(buf, fmt[prev:i]) + i++ // Skip % + if i >= len(fmt) { + return + } + + next := fmt[i] as rune + if next == #rune "%" { + print_string_to_buffer(buf, "%") + i++ + prev = i + continue + } + + index := implicit_index + set_prev := true + + if is_digit(next) { + index, i = parse_int(fmt, i) + } + + if 0 <= index && index < len(args) { + print_any_to_buffer(buf, args[index]) + implicit_index = index+1 + } else { + // TODO(bill): Error check index out bounds + print_string_to_buffer(buf, "") + } + + prev = i + } + + print_string_to_buffer(buf, fmt[prev:]) } +PRINT_BUF_SIZE :: 1<<12 -print :: proc(args: ..any) { - data: [4096]byte +print_to_file :: proc(f: ^File, fmt: string, args: ..any) { + data: [PRINT_BUF_SIZE]byte buf := data[:0] - print_to_buffer(^buf, ..args) - file_write(file_get_standard(File_Standard.OUTPUT), buf) + print_to_buffer(^buf, fmt, ..args) + file_write(f, buf) } - -println :: proc(args: ..any) { - data: [4096]byte +println_to_file :: proc(f: ^File, fmt: string, args: ..any) { + data: [PRINT_BUF_SIZE]byte buf := data[:0] - println_to_buffer(^buf, ..args) - file_write(file_get_standard(File_Standard.OUTPUT), buf) + print_to_buffer(^buf, fmt, ..args) + print_nl_to_buffer(^buf) + file_write(f, buf) +} + + +print :: proc(fmt: string, args: ..any) { + print_to_file(file_get_standard(File_Standard.OUTPUT), fmt, ..args) +} +print_err :: proc(fmt: string, args: ..any) { + print_to_file(file_get_standard(File_Standard.ERROR), fmt, ..args) +} +println :: proc(fmt: string, args: ..any) { + println_to_file(file_get_standard(File_Standard.OUTPUT), fmt, ..args) +} +println_err :: proc(fmt: string, args: ..any) { + println_to_file(file_get_standard(File_Standard.ERROR), fmt, ..args) } diff --git a/code/runtime.odin b/code/runtime.odin index aedcdc9ba..5f42c39c5 100644 --- a/code/runtime.odin +++ b/code/runtime.odin @@ -290,17 +290,23 @@ __assert :: proc(msg: string) { __debug_trap() } -__abc_error :: proc(file: string, line, column: int, index, len: int) { - print(file, "(", line, ":", line, ") Index `", index, "` is of bounds range [0, ", len, ")\n") +__bounds_check_error :: proc(file: string, line, column: int, + index, count: int) { + println_err("%(%:%) Index % is out of bounds range [0, %)", + file, line, column, index, count) __debug_trap() } -__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) { - print(file, "(", line, ":", line, ") Invalid slice indices: [", low, ":", high, ":", max, "]\n") +__slice_expr_error :: proc(file: string, line, column: int, + low, high, max: int) { + print_err("%(%:%) Invalid slice indices: [%:%:%]\n", + file, line, column, low, high, max) __debug_trap() } -__substring_expr_error :: proc(file: string, line, column: int, low, high: int) { - print(file, "(", line, ":", line, ") Invalid substring indices: [", low, ":", high, "]\n") +__substring_expr_error :: proc(file: string, line, column: int, + low, high: int) { + print_err("%(%:%) Invalid substring indices: [%:%:%]\n", + file, line, column, low, high) __debug_trap() } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 9d83cca69..0c89d1580 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -52,6 +52,10 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu return true; } + if (operand->mode == Addressing_Builtin) { + return false; + } + Type *s = operand->type; if (are_types_identical(s, type)) { diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index f6c621a9d..4df5daccf 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -42,13 +42,13 @@ void ssa_gen_destroy(ssaGen *s) { void ssa_gen_tree(ssaGen *s) { if (v_zero == NULL) { - v_zero = ssa_make_value_constant(gb_heap_allocator(), t_int, make_exact_value_integer(0)); - v_one = ssa_make_value_constant(gb_heap_allocator(), t_int, make_exact_value_integer(1)); - v_zero32 = ssa_make_value_constant(gb_heap_allocator(), t_i32, make_exact_value_integer(0)); - v_one32 = ssa_make_value_constant(gb_heap_allocator(), t_i32, make_exact_value_integer(1)); - v_two32 = ssa_make_value_constant(gb_heap_allocator(), t_i32, make_exact_value_integer(2)); - v_false = ssa_make_value_constant(gb_heap_allocator(), t_bool, make_exact_value_bool(false)); - v_true = ssa_make_value_constant(gb_heap_allocator(), t_bool, make_exact_value_bool(true)); + v_zero = ssa_make_const_int (gb_heap_allocator(), 0); + v_one = ssa_make_const_int (gb_heap_allocator(), 1); + v_zero32 = ssa_make_const_i32 (gb_heap_allocator(), 0); + v_one32 = ssa_make_const_i32 (gb_heap_allocator(), 1); + v_two32 = ssa_make_const_i32 (gb_heap_allocator(), 2); + v_false = ssa_make_const_bool(gb_heap_allocator(), false); + v_true = ssa_make_const_bool(gb_heap_allocator(), true); } struct ssaGlobalVariable { @@ -90,7 +90,7 @@ void ssa_gen_tree(ssaGen *s) { ExactValue v = tav->value; if (v.kind == ExactValue_String) { // NOTE(bill): The printer will fix the value correctly - g->Global.value = ssa_add_global_string_array(m, v); + g->Global.value = ssa_add_global_string_array(m, v.value_string); } else { g->Global.value = ssa_make_value_constant(a, tav->type, v); } @@ -231,7 +231,7 @@ void ssa_gen_tree(ssaGen *s) { // TODO(bill): Which is better? The mangled name or actual name? // ssaValue *gsa = ssa_add_global_string_array(proc, make_exact_value_string(t->Named.name)); - ssaValue *gsa = ssa_add_global_string_array(m, make_exact_value_string(t->Named.type_name->token.string)); + ssaValue *gsa = ssa_add_global_string_array(m, t->Named.type_name->token.string); ssaValue *elem = ssa_array_elem(proc, gsa); ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, gsa)); ssaValue *name = ssa_emit_string(proc, elem, len); @@ -261,8 +261,8 @@ void ssa_gen_tree(ssaGen *s) { case Basic_uint: { tag = ssa_add_local_generated(proc, t_type_info_integer); b32 is_unsigned = (basic_types[t->Basic.kind].flags & BasicFlag_Unsigned) != 0; - ssaValue *bits = ssa_make_value_constant(a, t_int, make_exact_value_integer(type_size_of(m->sizes, a, t))); - ssaValue *is_signed = ssa_make_value_constant(a, t_bool, make_exact_value_bool(!is_unsigned)); + ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t)); + ssaValue *is_signed = ssa_make_const_bool(a, !is_unsigned); ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits); ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), is_signed); } break; @@ -270,7 +270,7 @@ void ssa_gen_tree(ssaGen *s) { case Basic_f32: case Basic_f64: { tag = ssa_add_local_generated(proc, t_type_info_float); - ssaValue *bits = ssa_make_value_constant(a, t_int, make_exact_value_integer(type_size_of(m->sizes, a, t))); + ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t)); ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_int_ptr), bits); } break; @@ -296,10 +296,10 @@ void ssa_gen_tree(ssaGen *s) { isize ez = type_size_of(m->sizes, a, t->Array.elem); ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr); - ssa_emit_store(proc, elem_size, ssa_make_value_constant(a, t_int, make_exact_value_integer(ez))); + ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez)); ssaValue *count = ssa_emit_struct_gep(proc, tag, v_two32, t_int_ptr); - ssa_emit_store(proc, count, ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Array.count))); + ssa_emit_store(proc, count, ssa_make_const_int(a, t->Array.count)); } break; case Type_Slice: { @@ -309,7 +309,7 @@ void ssa_gen_tree(ssaGen *s) { isize ez = type_size_of(m->sizes, a, t->Slice.elem); ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr); - ssa_emit_store(proc, elem_size, ssa_make_value_constant(a, t_int, make_exact_value_integer(ez))); + ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez)); } break; case Type_Vector: { @@ -319,10 +319,10 @@ void ssa_gen_tree(ssaGen *s) { isize ez = type_size_of(m->sizes, a, t->Vector.elem); ssaValue *elem_size = ssa_emit_struct_gep(proc, tag, v_one32, t_int_ptr); - ssa_emit_store(proc, elem_size, ssa_make_value_constant(a, t_int, make_exact_value_integer(ez))); + ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez)); ssaValue *count = ssa_emit_struct_gep(proc, tag, v_two32, t_int_ptr); - ssa_emit_store(proc, count, ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Vector.count))); + ssa_emit_store(proc, count, ssa_make_const_int(a, t->Vector.count)); } break; case Type_Record: { @@ -341,22 +341,22 @@ void ssa_gen_tree(ssaGen *s) { GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field); isize source_index = f->Variable.field_index; - ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_value_constant(a, t_int, make_exact_value_integer(source_index))); + ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index)); ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr); ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr); ssaValue *offset = ssa_emit_struct_gep(proc, field, v_two32, t_int_ptr); if (f->token.string.len > 0) { - ssa_emit_store(proc, name, ssa_emit_global_string(proc, make_exact_value_string(f->token.string))); + ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string)); } ssa_emit_store(proc, type_info, tip); - ssa_emit_store(proc, offset, ssa_make_value_constant(a, t_int, make_exact_value_integer(foffset))); + ssa_emit_store(proc, offset, ssa_make_const_int(a, foffset)); } Type *slice_type = make_type_slice(a, t_type_info_member); Type *slice_type_ptr = make_type_pointer(a, slice_type); ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr); - ssaValue *field_count = ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Record.field_count)); + ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count); ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr)); ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr)); @@ -375,7 +375,7 @@ void ssa_gen_tree(ssaGen *s) { ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index); for (isize i = 0; i < t->Record.field_count; i++) { - ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_value_constant(a, t_int, make_exact_value_integer(i))); + ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i)); ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr); ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr); ssaValue *offset = ssa_emit_struct_gep(proc, field, v_two32, t_int_ptr); @@ -384,16 +384,16 @@ void ssa_gen_tree(ssaGen *s) { ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type); if (f->token.string.len > 0) { - ssa_emit_store(proc, name, ssa_emit_global_string(proc, make_exact_value_string(f->token.string))); + ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string)); } ssa_emit_store(proc, type_info, tip); - ssa_emit_store(proc, offset, ssa_make_value_constant(a, t_int, make_exact_value_integer(0))); + ssa_emit_store(proc, offset, ssa_make_const_int(a, 0)); } Type *slice_type = make_type_slice(a, t_type_info_member); Type *slice_type_ptr = make_type_pointer(a, slice_type); ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr); - ssaValue *field_count = ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Record.field_count)); + ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count); ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr)); ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr)); @@ -421,7 +421,7 @@ void ssa_gen_tree(ssaGen *s) { ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index); for (isize i = 0; i < t->Tuple.variable_count; i++) { - ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_value_constant(a, t_int, make_exact_value_integer(i))); + ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i)); ssaValue *name = ssa_emit_struct_gep(proc, field, v_zero32, t_string_ptr); ssaValue *type_info = ssa_emit_struct_gep(proc, field, v_one32, t_type_info_ptr_ptr); // NOTE(bill): offset is not used for tuples @@ -430,7 +430,7 @@ void ssa_gen_tree(ssaGen *s) { ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type); if (f->token.string.len > 0) { - ssa_emit_store(proc, name, ssa_emit_global_string(proc, make_exact_value_string(f->token.string))); + ssa_emit_store(proc, name, ssa_emit_global_string(proc, f->token.string)); } ssa_emit_store(proc, type_info, tip); } @@ -438,7 +438,7 @@ void ssa_gen_tree(ssaGen *s) { Type *slice_type = make_type_slice(a, t_type_info_member); Type *slice_type_ptr = make_type_pointer(a, slice_type); ssaValue *slice = ssa_emit_struct_gep(proc, tag, v_zero32, slice_type_ptr); - ssaValue *variable_count = ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Tuple.variable_count)); + ssaValue *variable_count = ssa_make_const_int(a, t->Tuple.variable_count); ssaValue *elem = ssa_emit_struct_gep(proc, slice, v_zero32, make_type_pointer(a, t_type_info_member_ptr)); ssaValue *len = ssa_emit_struct_gep(proc, slice, v_one32, make_type_pointer(a, t_int_ptr)); @@ -459,7 +459,7 @@ void ssa_gen_tree(ssaGen *s) { ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params)); ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results)); - ssa_emit_store(proc, variadic, ssa_make_value_constant(a, t_bool, make_exact_value_bool(t->Proc.variadic))); + ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic)); // TODO(bill): Type_Info for procedures } break; diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 569582b1a..ee4b33119 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -318,7 +318,7 @@ void ssa_init_module(ssaModule *m, Checker *c) { // Default states m->stmt_state_flags = 0; - m->stmt_state_flags |= StmtStateFlag_abc; + m->stmt_state_flags |= StmtStateFlag_bounds_check; { // Add type info data @@ -650,6 +650,17 @@ ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) { return v; } +ssaValue *ssa_make_const_int(gbAllocator a, i64 i) { + return ssa_make_value_constant(a, t_int, make_exact_value_integer(i)); +} +ssaValue *ssa_make_const_i32(gbAllocator a, i64 i) { + return ssa_make_value_constant(a, t_i32, make_exact_value_integer(i)); +} +ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) { + return ssa_make_value_constant(a, t_bool, make_exact_value_bool(b != 0)); +} + + ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Type *type, AstNode *type_expr, AstNode *body, String name) { ssaValue *v = ssa_alloc_value(a, ssaValue_Proc); v->Proc.module = m; @@ -791,7 +802,9 @@ ssaValue *ssa_emit_global_call(ssaProcedure *proc, char *name_, ssaValue **args, Type *ssa_addr_type(ssaAddr lval) { if (lval.addr != NULL) { - return type_deref(ssa_type(lval.addr)); + Type *t = ssa_type(lval.addr); + GB_ASSERT(is_type_pointer(t)); + return type_deref(t); } return NULL; } @@ -1210,7 +1223,7 @@ ssaValue *ssa_array_elem(ssaProcedure *proc, ssaValue *array) { ssaValue *ssa_array_len(ssaProcedure *proc, ssaValue *array) { Type *t = ssa_type(array); GB_ASSERT(t->kind == Type_Array); - return ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(t->Array.count)); + return ssa_make_const_int(proc->module->allocator, t->Array.count); } ssaValue *ssa_array_cap(ssaProcedure *proc, ssaValue *array) { return ssa_array_len(proc, array); @@ -1302,8 +1315,7 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba } -ssaValue *ssa_add_global_string_array(ssaModule *m, ExactValue value) { - GB_ASSERT(value.kind == ExactValue_String); +ssaValue *ssa_add_global_string_array(ssaModule *m, String string) { gbAllocator a = gb_heap_allocator(); isize max_len = 4+8+1; @@ -1314,9 +1326,10 @@ ssaValue *ssa_add_global_string_array(ssaModule *m, ExactValue value) { String name = make_string(str, len-1); Token token = {Token_String}; token.string = name; - Type *type = make_type_array(a, t_u8, value.value_string.len); - Entity *entity = make_entity_constant(a, NULL, token, type, value); - ssaValue *g = ssa_make_value_global(a, entity, ssa_make_value_constant(a, type, value)); + Type *type = make_type_array(a, t_u8, string.len); + ExactValue ev = make_exact_value_string(string); + Entity *entity = make_entity_constant(a, NULL, token, type, ev); + ssaValue *g = ssa_make_value_global(a, entity, ssa_make_value_constant(a, type, ev)); g->Global.is_private = true; // g->Global.is_constant = true; @@ -1341,11 +1354,10 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) { } -ssaValue *ssa_emit_global_string(ssaProcedure *proc, ExactValue value) { - GB_ASSERT(value.kind == ExactValue_String); - ssaValue *global_array = ssa_add_global_string_array(proc->module, value); +ssaValue *ssa_emit_global_string(ssaProcedure *proc, String str) { + ssaValue *global_array = ssa_add_global_string_array(proc->module, str); ssaValue *elem = ssa_array_elem(proc, global_array); - ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, global_array)); + ssaValue *len = ssa_make_const_int(proc->module->allocator, str.len); return ssa_emit_string(proc, elem, len); } @@ -1488,7 +1500,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg ssa_emit_comment(proc, make_string("union - child to parent")); gbAllocator allocator = proc->module->allocator; ssaValue *parent = ssa_add_local_generated(proc, t); - ssaValue *tag = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(i)); + ssaValue *tag = ssa_make_const_int(allocator, i); ssa_emit_store(proc, ssa_emit_struct_gep(proc, parent, v_one32, t_int), tag); ssaValue *data = ssa_emit_conv(proc, parent, t_rawptr); @@ -1587,7 +1599,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg ssaValue *result = ssa_add_local_generated(proc, t_any); ssaValue *data = NULL; - if (value->kind == ssaValue_Instr && + if (false && value->kind == ssaValue_Instr && value->Instr.kind == ssaInstr_Load) { // NOTE(bill): Addressable value data = value->Instr.Load.address; @@ -1657,7 +1669,7 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) { // IMPORTANT TODO(bill): THIS ONLY DOES ONE LAYER DEEP!!! FUCKING HELL THIS IS NOT WHAT I SIGNED UP FOR! i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel); - ssaValue *offset = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(-offset_)); + ssaValue *offset = ssa_make_const_int(allocator, -offset_); ssaValue *head = ssa_emit_ptr_offset(proc, bytes, offset); return ssa_emit_conv(proc, head, t); } @@ -1689,41 +1701,36 @@ ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) { void ssa_array_bounds_check(ssaProcedure *proc, Token token, ssaValue *index, ssaValue *len) { - if ((proc->module->stmt_state_flags & StmtStateFlag_no_abc) != 0) { + if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { return; } ssa_emit_comment(proc, make_string("ArrayBoundsCheck")); - index = ssa_emit_conv(proc, index, t_int); - len = ssa_emit_conv(proc, len, t_int); + len = ssa_emit_conv(proc, len, t_int); + Token le = {Token_LtEq}; Token lt = {Token_Lt}; - Token ge = {Token_GtEq}; - Token cmp_or = {Token_Or}; // NOTE(bill): Just `or` it as both sides have been evaluated anyway - ssaValue *lower = ssa_emit_comp(proc, lt, index, v_zero); - ssaValue *upper = ssa_emit_comp(proc, ge, index, len); - ssaValue *cond = ssa_emit_arith(proc, cmp_or, lower, upper, t_bool); + Token cmp_and = {Token_And}; // NOTE(bill): Doesn't need to be logical + ssaValue *c0 = ssa_emit_comp(proc, le, v_zero, index); + ssaValue *c1 = ssa_emit_comp(proc, lt, index, len); + ssaValue *cond = ssa_emit_comp(proc, cmp_and, c0, c1); ssaBlock *then = ssa_add_block(proc, NULL, make_string("abc.then")); - ssaBlock *done = ssa__make_block(proc, NULL, make_string("abc.done")); // NOTE(bill): Append later + ssaBlock *done = ssa__make_block(proc, NULL, make_string("abc.done")); - ssa_emit_if(proc, cond, then, done); + ssa_emit_if(proc, cond, done, then); proc->curr_block = then; + gbAllocator a = proc->module->allocator; - - ssaValue *file = ssa_emit_global_string(proc, make_exact_value_string(token.pos.file)); - ssaValue *line = ssa_make_value_constant(a, t_int, make_exact_value_integer(token.pos.line)); - ssaValue *column = ssa_make_value_constant(a, t_int, make_exact_value_integer(token.pos.column)); - ssaValue **args = gb_alloc_array(a, ssaValue *, 5); - args[0] = file; - args[1] = line; - args[2] = column; + args[0] = ssa_emit_global_string(proc, token.pos.file); + args[1] = ssa_make_const_int(a, token.pos.line); + args[2] = ssa_make_const_int(a, token.pos.column); args[3] = index; args[4] = len; - ssa_emit_global_call(proc, "__abc_error", args, 5); + ssa_emit_global_call(proc, "__bounds_check_error", args, 5); ssa_emit_jump(proc, done); gb_array_append(proc->blocks, done); @@ -1731,52 +1738,42 @@ void ssa_array_bounds_check(ssaProcedure *proc, Token token, ssaValue *index, ss } void ssa_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaValue *high, ssaValue *max, b32 is_substring) { - if ((proc->module->stmt_state_flags & StmtStateFlag_no_abc) != 0) { + if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { return; } - ssa_emit_comment(proc, make_string("SliceBoundsCheck")); low = ssa_emit_conv(proc, low, t_int); high = ssa_emit_conv(proc, high, t_int); max = ssa_emit_conv(proc, max, t_int); - Token lt = {Token_Lt}; - Token gt = {Token_Gt}; - Token cmp_or = {Token_Or}; // NOTE(bill): Just `or` it as both sides have been evaluated anyway - ssaValue *c0 = ssa_emit_comp(proc, lt, low, v_zero); - ssaValue *c1 = ssa_emit_comp(proc, gt, low, high); - ssaValue *c2 = ssa_emit_comp(proc, gt, low, max); - ssaValue *c3 = ssa_emit_comp(proc, gt, high, max); + Token le = {Token_LtEq}; + Token cmp_and = {Token_And}; // NOTE(bill): Doesn't need to be logical + ssaValue *c0 = ssa_emit_comp(proc, le, v_zero, low); + ssaValue *c1 = ssa_emit_comp(proc, le, low, high); + ssaValue *c2 = ssa_emit_comp(proc, le, high, max); ssaValue *cond = NULL; - cond = ssa_emit_arith(proc, cmp_or, c0, c1, t_bool); - cond = ssa_emit_arith(proc, cmp_or, c2, cond, t_bool); - cond = ssa_emit_arith(proc, cmp_or, c3, cond, t_bool); + cond = ssa_emit_comp(proc, cmp_and, c0, c1); + cond = ssa_emit_comp(proc, cmp_and, cond, c2); + ssaBlock *then = ssa_add_block(proc, NULL, make_string("seb.then")); + ssaBlock *done = ssa__make_block(proc, NULL, make_string("seb.done")); - ssaBlock *then = ssa_add_block(proc, NULL, make_string("slice.expr.then")); - ssaBlock *done = ssa__make_block(proc, NULL, make_string("slice.expr.done")); // NOTE(bill): Append later - - ssa_emit_if(proc, cond, then, done); + ssa_emit_if(proc, cond, done, then); proc->curr_block = then; gbAllocator a = proc->module->allocator; - - ssaValue *file = ssa_emit_global_string(proc, make_exact_value_string(token.pos.file)); - ssaValue *line = ssa_make_value_constant(a, t_int, make_exact_value_integer(token.pos.line)); - ssaValue *column = ssa_make_value_constant(a, t_int, make_exact_value_integer(token.pos.column)); - ssaValue **args = gb_alloc_array(a, ssaValue *, 6); - args[0] = file; - args[1] = line; - args[2] = column; + args[0] = ssa_emit_global_string(proc, token.pos.file); + args[1] = ssa_make_const_int(a, token.pos.line); + args[2] = ssa_make_const_int(a, token.pos.column); args[3] = low; args[4] = high; args[5] = max; - if (is_substring) { - ssa_emit_global_call(proc, "__substring_expr_error", args, 5); - } else { + if (!is_substring) { ssa_emit_global_call(proc, "__slice_expr_error", args, 6); + } else { + ssa_emit_global_call(proc, "__substring_expr_error", args, 5); } ssa_emit_jump(proc, done); @@ -1950,7 +1947,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue Type *t = ssa_type(field_elem); GB_ASSERT(t->kind != Type_Tuple); ssaValue *ev = ssa_emit_conv(proc, field_elem, et); - ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(index)); + ssaValue *i = ssa_make_const_int(proc->module->allocator, index); result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i)); } if (index == 1 && base_type->Vector.count > 1) { @@ -2066,8 +2063,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue i64 a = type_align_of(proc->module->sizes, allocator, type); ssaValue **args = gb_alloc_array(allocator, ssaValue *, 2); - args[0] = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(s)); - args[1] = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(a)); + args[0] = ssa_make_const_int(allocator, s); + args[1] = ssa_make_const_int(allocator, a); ssaValue *call = ssa_emit_global_call(proc, "alloc_align", args, 2); ssaValue *v = ssa_emit_conv(proc, call, ptr_type); return v; @@ -2085,8 +2082,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue i64 s = type_size_of(proc->module->sizes, allocator, type); i64 a = type_align_of(proc->module->sizes, allocator, type); - ssaValue *elem_size = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(s)); - ssaValue *elem_align = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(a)); + ssaValue *elem_size = ssa_make_const_int(allocator, s); + ssaValue *elem_align = ssa_make_const_int(allocator, a); ssaValue *len = ssa_build_expr(proc, ce->args[1]); ssaValue *cap = len; @@ -2161,9 +2158,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue LIT(pos.file), pos.line, pos.column, expr); err_len--; - ssaValue *array = ssa_add_global_string_array(proc->module, make_exact_value_string(make_string(err_str, err_len))); + ssaValue *array = ssa_add_global_string_array(proc->module, make_string(err_str, err_len)); ssaValue *elem = ssa_array_elem(proc, array); - ssaValue *len = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(err_len)); + ssaValue *len = ssa_make_const_int(proc->module->allocator, err_len); ssaValue *string = ssa_emit_string(proc, elem, len); ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 1); @@ -2219,8 +2216,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *cond = ssa_emit_comp(proc, lt, len_dst, len_src); ssaValue *len = ssa_emit_select(proc, cond, len_dst, len_src); Token mul = {Token_Mul}; - ssaValue *elem_size = ssa_make_value_constant(proc->module->allocator, t_int, - make_exact_value_integer(size_of_elem)); + ssaValue *elem_size = ssa_make_const_int(proc->module->allocator, size_of_elem); ssaValue *byte_count = ssa_emit_arith(proc, mul, len, elem_size, t_int); ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 3); @@ -2264,8 +2260,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // Add new slice item i64 item_size = type_size_of(proc->module->sizes, proc->module->allocator, elem_type); - ssaValue *byte_count = ssa_make_value_constant(proc->module->allocator, t_int, - make_exact_value_integer(item_size)); + ssaValue *byte_count = ssa_make_const_int(proc->module->allocator, item_size); ssaValue *offset = ssa_emit_ptr_offset(proc, elem, len); offset = ssa_emit_conv(proc, offset, t_rawptr, true); @@ -2333,8 +2328,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *v = ssa_emit_arith(proc, sub, ptr_a, ptr_b, t_int); if (elem_size > 1) { Token quo = {Token_Quo}; - ssaValue *ez = ssa_make_value_constant(proc->module->allocator, t_int, - make_exact_value_integer(elem_size)); + ssaValue *ez = ssa_make_const_int(proc->module->allocator, elem_size); v = ssa_emit_arith(proc, quo, v, ez, t_int); } @@ -2477,7 +2471,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *base_elem = ssa_emit_struct_gep(proc, base_array, v_zero32, elem_ptr_type); ssaValue *slice_elem = ssa_emit_struct_gep(proc, slice, v_zero32, elem_ptr_type); ssa_emit_store(proc, slice_elem, base_elem); - ssaValue *len = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(slice_len)); + ssaValue *len = ssa_make_const_int(allocator, slice_len); ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_one32, t_int), len); ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), len); } @@ -2517,7 +2511,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { // TODO(bill): Optimize by not allocating everytime if (tv->value.value_string.len > 0) { - return ssa_emit_global_string(proc, tv->value); + return ssa_emit_global_string(proc, tv->value.value_string); } else { ssaValue *null_string = ssa_add_local_generated(proc, t_string); return ssa_emit_load(proc, null_string); @@ -2648,7 +2642,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { // HACK(bill): Fix how lvalues for vectors work ssaValue *vector = ssa_build_addr(proc, ie->expr).addr; ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); - ssaValue *len = ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Vector.count)); + ssaValue *len = ssa_make_const_int(a, t->Vector.count); ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len); return ssa_make_addr_vector(vector, index, expr); } break; @@ -2658,7 +2652,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { Type *et = make_type_pointer(proc->module->allocator, t->Array.elem); ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); ssaValue *elem = ssa_emit_struct_gep(proc, array, index, et); - ssaValue *len = ssa_make_value_constant(a, t_int, make_exact_value_integer(t->Vector.count)); + ssaValue *len = ssa_make_const_int(a, t->Vector.count); ssa_array_bounds_check(proc, ast_node_token(ie->index), index, len); return ssa_make_addr(elem, expr); } break; @@ -2679,9 +2673,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { ssaValue *elem = NULL; ssaValue *len = NULL; if (tv->mode == Addressing_Constant) { - ssaValue *array = ssa_add_global_string_array(proc->module, tv->value); + ssaValue *array = ssa_add_global_string_array(proc->module, tv->value.value_string); elem = ssa_array_elem(proc, array); - len = ssa_make_value_constant(a, t_int, make_exact_value_integer(tv->value.value_string.len)); + len = ssa_make_const_int(a, tv->value.value_string.len); } else { ssaValue *str = ssa_build_expr(proc, ie->expr); elem = ssa_string_elem(proc, str); @@ -2922,12 +2916,12 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { u32 out = proc->module->stmt_state_flags; defer (proc->module->stmt_state_flags = out); - if (in & StmtStateFlag_abc) { - out |= StmtStateFlag_abc; - out &= ~StmtStateFlag_no_abc; - } else if (in & StmtStateFlag_no_abc) { - out |= StmtStateFlag_no_abc; - out &= ~StmtStateFlag_abc; + if (in & StmtStateFlag_bounds_check) { + out |= StmtStateFlag_bounds_check; + out &= ~StmtStateFlag_no_bounds_check; + } else if (in & StmtStateFlag_no_bounds_check) { + out |= StmtStateFlag_no_bounds_check; + out &= ~StmtStateFlag_bounds_check; } } @@ -3481,7 +3475,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { for (isize field_index = 1; field_index < ut->Record.field_count; field_index++) { Entity *f = get_base_type(union_type)->Record.fields[field_index]; if (are_types_identical(f->type, base_type)) { - index = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(field_index)); + index = ssa_make_const_int(allocator, field_index); break; } } @@ -3581,12 +3575,12 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) { u32 out = proc->module->stmt_state_flags; defer (proc->module->stmt_state_flags = out); - if (in & ProcTag_abc) { - out |= ProcTag_abc; - out &= ~ProcTag_no_abc; - } else if (in & ProcTag_no_abc) { - out |= ProcTag_no_abc; - out &= ~ProcTag_abc; + if (in & ProcTag_bounds_check) { + out |= ProcTag_bounds_check; + out &= ~ProcTag_no_bounds_check; + } else if (in & ProcTag_no_bounds_check) { + out |= ProcTag_no_bounds_check; + out &= ~ProcTag_bounds_check; } } diff --git a/src/parser.cpp b/src/parser.cpp index 74a4fb71e..356d51da3 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -59,11 +59,11 @@ enum DeclKind { }; enum ProcTag { - ProcTag_abc = GB_BIT(0), - ProcTag_no_abc = GB_BIT(1), - ProcTag_foreign = GB_BIT(2), - ProcTag_inline = GB_BIT(3), - ProcTag_no_inline = GB_BIT(4), + ProcTag_bounds_check = GB_BIT(0), + ProcTag_no_bounds_check = GB_BIT(1), + ProcTag_foreign = GB_BIT(2), + ProcTag_inline = GB_BIT(3), + ProcTag_no_inline = GB_BIT(4), }; enum VarDeclTag { @@ -78,8 +78,8 @@ enum TypeFlag : u32 { }; enum StmtStateFlag : u32 { - StmtStateFlag_abc = GB_BIT(0), - StmtStateFlag_no_abc = GB_BIT(1), + StmtStateFlag_bounds_check = GB_BIT(0), + StmtStateFlag_no_bounds_check = GB_BIT(1), }; @@ -1177,10 +1177,10 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) { check_proc_add_tag(f, tag_expr, tags, ProcTag_inline, tag_name); } else if (are_strings_equal(tag_name, make_string("no_inline"))) { check_proc_add_tag(f, tag_expr, tags, ProcTag_no_inline, tag_name); - } else if (are_strings_equal(tag_name, make_string("abc"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_abc, tag_name); - } else if (are_strings_equal(tag_name, make_string("no_abc"))) { - check_proc_add_tag(f, tag_expr, tags, ProcTag_no_abc, tag_name); + } else if (are_strings_equal(tag_name, make_string("bounds_check"))) { + check_proc_add_tag(f, tag_expr, tags, ProcTag_bounds_check, tag_name); + } else if (are_strings_equal(tag_name, make_string("no_bounds_check"))) { + check_proc_add_tag(f, tag_expr, tags, ProcTag_no_bounds_check, tag_name); } else { ast_file_err(f, ast_node_token(tag_expr), "Unknown procedure tag"); } @@ -1190,12 +1190,12 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) { ast_file_err(f, f->cursor[0], "You cannot apply both #inline and #no_inline to a procedure"); } - if ((*tags & ProcTag_abc) && (*tags & ProcTag_no_abc)) { - ast_file_err(f, f->cursor[0], "You cannot apply both #abc and #no_abc to a procedure"); + if ((*tags & ProcTag_bounds_check) && (*tags & ProcTag_no_bounds_check)) { + ast_file_err(f, f->cursor[0], "You cannot apply both #bounds_check and #no_bounds_check to a procedure"); } - if (((*tags & ProcTag_abc) || (*tags & ProcTag_no_abc)) && (*tags & ProcTag_foreign)) { - ast_file_err(f, f->cursor[0], "You cannot apply both #abc or #no_abc to a procedure without a body"); + if (((*tags & ProcTag_bounds_check) || (*tags & ProcTag_no_bounds_check)) && (*tags & ProcTag_foreign)) { + ast_file_err(f, f->cursor[0], "You cannot apply both #bounds_check or #no_bounds_check to a procedure without a body"); } } @@ -2540,18 +2540,18 @@ AstNode *parse_stmt(AstFile *f) { } var_decl->VarDecl.tags |= VarDeclTag_thread_local; return var_decl; - } else if (are_strings_equal(tag, make_string("abc"))) { + } else if (are_strings_equal(tag, make_string("bounds_check"))) { s = parse_stmt(f); - s->stmt_state_flags |= StmtStateFlag_abc; - if ((s->stmt_state_flags & StmtStateFlag_no_abc) != 0) { - ast_file_err(f, token, "#abc and #no_abc cannot be applied together"); + s->stmt_state_flags |= StmtStateFlag_bounds_check; + if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { + ast_file_err(f, token, "#bounds_check and #no_bounds_check cannot be applied together"); } return s; - } else if (are_strings_equal(tag, make_string("no_abc"))) { + } else if (are_strings_equal(tag, make_string("no_bounds_check"))) { s = parse_stmt(f); - s->stmt_state_flags |= StmtStateFlag_no_abc; - if ((s->stmt_state_flags & StmtStateFlag_abc) != 0) { - ast_file_err(f, token, "#abc and #no_abc cannot be applied together"); + s->stmt_state_flags |= StmtStateFlag_no_bounds_check; + if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) { + ast_file_err(f, token, "#bounds_check and #no_bounds_check cannot be applied together"); } return s; }