mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Finally fix signed integer conversion and printing
This commit is contained in:
+4
-4
@@ -9,10 +9,10 @@
|
|||||||
#import "sync.odin";
|
#import "sync.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
x := 2;
|
a: i8 = -1;
|
||||||
y := 3;
|
fmt.println(a, cast(u64)a, cast(i64)a);
|
||||||
z := x+y;
|
b: i64 = -1;
|
||||||
fmt.println(z);
|
fmt.println(b, cast(u64)b, cast(i64)b);
|
||||||
|
|
||||||
when false {
|
when false {
|
||||||
s := new_slice(int, 0, 10);
|
s := new_slice(int, 0, 10);
|
||||||
|
|||||||
+62
-31
@@ -102,7 +102,7 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
default:
|
default:
|
||||||
write_string(buf, info.signed ? "i" : "u");
|
write_string(buf, info.signed ? "i" : "u");
|
||||||
fi := Fmt_Info{buf = buf};
|
fi := Fmt_Info{buf = buf};
|
||||||
fmt_int(^fi, cast(u64)(8*info.size), false, 'd');
|
fmt_int(^fi, cast(u64)(8*info.size), false, 64, 'd');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Float:
|
case Float:
|
||||||
@@ -155,7 +155,7 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
case Array:
|
case Array:
|
||||||
write_string(buf, "[");
|
write_string(buf, "[");
|
||||||
fi := Fmt_Info{buf = buf};
|
fi := Fmt_Info{buf = buf};
|
||||||
fmt_int(^fi, cast(u64)info.count, false, 'd');
|
fmt_int(^fi, cast(u64)info.count, false, 64, 'd');
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
case Dynamic_Array:
|
case Dynamic_Array:
|
||||||
@@ -168,7 +168,7 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
case Vector:
|
case Vector:
|
||||||
write_string(buf, "[vector ");
|
write_string(buf, "[vector ");
|
||||||
fi := Fmt_Info{buf = buf};
|
fi := Fmt_Info{buf = buf};
|
||||||
fmt_int(^fi, cast(u64)info.count, false, 'd');
|
fmt_int(^fi, cast(u64)info.count, false, 64, 'd');
|
||||||
write_string(buf, "]");
|
write_string(buf, "]");
|
||||||
write_type(buf, info.elem);
|
write_type(buf, info.elem);
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
if info.custom_align {
|
if info.custom_align {
|
||||||
write_string(buf, "#align ");
|
write_string(buf, "#align ");
|
||||||
fi := Fmt_Info{buf = buf};
|
fi := Fmt_Info{buf = buf};
|
||||||
fmt_int(^fi, cast(u64)info.align, false, 'd');
|
fmt_int(^fi, cast(u64)info.align, false, 64, 'd');
|
||||||
write_byte(buf, ' ');
|
write_byte(buf, ' ');
|
||||||
}
|
}
|
||||||
write_byte(buf, '{');
|
write_byte(buf, '{');
|
||||||
@@ -435,16 +435,47 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, neg: bool, digits: string) {
|
|
||||||
if neg {
|
is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned: u64, neg: bool) {
|
||||||
u = -u;
|
neg := false;
|
||||||
|
if is_signed {
|
||||||
|
match bit_size {
|
||||||
|
case 8:
|
||||||
|
i := cast(i8)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
case 16:
|
||||||
|
i := cast(i16)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
case 32:
|
||||||
|
i := cast(i32)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
case 64:
|
||||||
|
i := cast(i64)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
default:
|
||||||
|
panic("is_integer_negative: Unknown integer size");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return u, neg;
|
||||||
|
}
|
||||||
|
|
||||||
|
_write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, is_signed: bool, bit_size: int, digits: string) {
|
||||||
|
_, neg := is_integer_negative(u, is_signed, bit_size);
|
||||||
|
|
||||||
BUF_SIZE :: 256;
|
BUF_SIZE :: 256;
|
||||||
if fi.width_set || fi.prec_set {
|
if fi.width_set || fi.prec_set {
|
||||||
width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
|
width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
|
||||||
if width > BUF_SIZE {
|
if width > BUF_SIZE {
|
||||||
// TODO(bill):????
|
// TODO(bill):????
|
||||||
panic("_write_int buffer overrun. Width and precision too big");
|
panic("_write_int: buffer overrun. Width and precision too big");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,10 +506,10 @@ _write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, neg: bool, digits: string)
|
|||||||
|
|
||||||
buf: [256]byte;
|
buf: [256]byte;
|
||||||
flags: strconv.Int_Flag;
|
flags: strconv.Int_Flag;
|
||||||
if fi.hash { flags |= strconv.Int_Flag.PREFIX; }
|
if fi.hash { flags |= strconv.Int_Flag.PREFIX; }
|
||||||
if fi.plus { flags |= strconv.Int_Flag.PLUS; }
|
if fi.plus { flags |= strconv.Int_Flag.PLUS; }
|
||||||
if fi.space { flags |= strconv.Int_Flag.SPACE; }
|
if fi.space { flags |= strconv.Int_Flag.SPACE; }
|
||||||
s := strconv.append_bits(buf[..0], u, base, neg, digits, flags);
|
s := strconv.append_bits(buf[..0], u, base, is_signed, bit_size, digits, flags);
|
||||||
|
|
||||||
prev_zero := fi.zero;
|
prev_zero := fi.zero;
|
||||||
defer fi.zero = prev_zero;
|
defer fi.zero = prev_zero;
|
||||||
@@ -493,14 +524,14 @@ fmt_rune :: proc(fi: ^Fmt_Info, r: rune) {
|
|||||||
write_rune(fi.buf, r);
|
write_rune(fi.buf, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt_int :: proc(fi: ^Fmt_Info, u: u64, neg: bool, verb: rune) {
|
fmt_int :: proc(fi: ^Fmt_Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
|
||||||
match verb {
|
match verb {
|
||||||
case 'v': _write_int(fi, u, 10, neg, __DIGITS_LOWER);
|
case 'v': _write_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
|
||||||
case 'b': _write_int(fi, u, 2, neg, __DIGITS_LOWER);
|
case 'b': _write_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER);
|
||||||
case 'o': _write_int(fi, u, 8, neg, __DIGITS_LOWER);
|
case 'o': _write_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER);
|
||||||
case 'd': _write_int(fi, u, 10, neg, __DIGITS_LOWER);
|
case 'd': _write_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
|
||||||
case 'x': _write_int(fi, u, 16, neg, __DIGITS_LOWER);
|
case 'x': _write_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER);
|
||||||
case 'X': _write_int(fi, u, 16, neg, __DIGITS_UPPER);
|
case 'X': _write_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER);
|
||||||
case 'c', 'r':
|
case 'c', 'r':
|
||||||
fmt_rune(fi, cast(rune)u);
|
fmt_rune(fi, cast(rune)u);
|
||||||
case 'U':
|
case 'U':
|
||||||
@@ -509,7 +540,7 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, neg: bool, verb: rune) {
|
|||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
} else {
|
} else {
|
||||||
write_string(fi.buf, "U+");
|
write_string(fi.buf, "U+");
|
||||||
_write_int(fi, u, 16, false, __DIGITS_UPPER);
|
_write_int(fi, u, 16, false, bit_size, __DIGITS_UPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -598,7 +629,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
|||||||
if !fi.hash || verb == 'v' {
|
if !fi.hash || verb == 'v' {
|
||||||
write_string(fi.buf, "0x");
|
write_string(fi.buf, "0x");
|
||||||
}
|
}
|
||||||
_write_int(fi, u, 16, false, __DIGITS_UPPER);
|
_write_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||||
@@ -876,16 +907,16 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
|||||||
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
case f32: fmt_float(fi, cast(f64)a, 32, verb);
|
||||||
case f64: fmt_float(fi, a, 64, verb);
|
case f64: fmt_float(fi, a, 64, verb);
|
||||||
|
|
||||||
case int: fmt_int(fi, cast(u64)a, a < 0, verb);
|
case int: fmt_int(fi, cast(u64)a, true, 8*size_of(int), verb);
|
||||||
case i8: fmt_int(fi, cast(u64)a, a < 0, verb);
|
case i8: fmt_int(fi, cast(u64)a, true, 8, verb);
|
||||||
case i16: fmt_int(fi, cast(u64)a, a < 0, verb);
|
case i16: fmt_int(fi, cast(u64)a, true, 16, verb);
|
||||||
case i32: fmt_int(fi, cast(u64)a, a < 0, verb);
|
case i32: fmt_int(fi, cast(u64)a, true, 32, verb);
|
||||||
case i64: fmt_int(fi, cast(u64)a, a < 0, verb);
|
case i64: fmt_int(fi, cast(u64)a, true, 64, verb);
|
||||||
case uint: fmt_int(fi, cast(u64)a, false, verb);
|
case uint: fmt_int(fi, cast(u64)a, false, 8*size_of(uint), verb);
|
||||||
case u8: fmt_int(fi, cast(u64)a, false, verb);
|
case u8: fmt_int(fi, cast(u64)a, false, 8, verb);
|
||||||
case u16: fmt_int(fi, cast(u64)a, false, verb);
|
case u16: fmt_int(fi, cast(u64)a, false, 16, verb);
|
||||||
case u32: fmt_int(fi, cast(u64)a, false, verb);
|
case u32: fmt_int(fi, cast(u64)a, false, 32, verb);
|
||||||
case u64: fmt_int(fi, cast(u64)a, false, verb);
|
case u64: fmt_int(fi, cast(u64)a, false, 64, verb);
|
||||||
case string: fmt_string(fi, a, verb);
|
case string: fmt_string(fi, a, verb);
|
||||||
default: fmt_value(fi, arg, verb);
|
default: fmt_value(fi, arg, verb);
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-6
@@ -25,10 +25,10 @@ append_bool :: proc(buf: []byte, b: bool) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
append_uint :: proc(buf: []byte, u: u64, base: int) -> string {
|
append_uint :: proc(buf: []byte, u: u64, base: int) -> string {
|
||||||
return append_bits(buf, u, base, false, digits, 0);
|
return append_bits(buf, u, base, false, 8*size_of(uint), digits, 0);
|
||||||
}
|
}
|
||||||
append_int :: proc(buf: []byte, i: i64, base: int) -> string {
|
append_int :: proc(buf: []byte, i: i64, base: int) -> string {
|
||||||
return append_bits(buf, cast(u64)i, base, i < 0, digits, 0);
|
return append_bits(buf, cast(u64)i, base, true, 8*size_of(int), digits, 0);
|
||||||
}
|
}
|
||||||
itoa :: proc(buf: []byte, i: int) -> string {
|
itoa :: proc(buf: []byte, i: int) -> string {
|
||||||
return append_int(buf, cast(i64)i, 10);
|
return append_int(buf, cast(i64)i, 10);
|
||||||
@@ -265,7 +265,39 @@ MAX_BASE :: 32;
|
|||||||
immutable digits := "0123456789abcdefghijklmnopqrstuvwxyz";
|
immutable digits := "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
|
||||||
append_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, flags: Int_Flag) -> string {
|
is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned: u64, neg: bool) {
|
||||||
|
neg := false;
|
||||||
|
if is_signed {
|
||||||
|
match bit_size {
|
||||||
|
case 8:
|
||||||
|
i := cast(i8)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
case 16:
|
||||||
|
i := cast(i16)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
case 32:
|
||||||
|
i := cast(i32)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
case 64:
|
||||||
|
i := cast(i64)u;
|
||||||
|
neg = i < 0;
|
||||||
|
if neg { i = -i; }
|
||||||
|
u = cast(u64)i;
|
||||||
|
default:
|
||||||
|
panic("is_integer_negative: Unknown integer size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return u, neg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flag) -> string {
|
||||||
is_pow2 :: proc(x: i64) -> bool {
|
is_pow2 :: proc(x: i64) -> bool {
|
||||||
if (x <= 0) {
|
if (x <= 0) {
|
||||||
return false;
|
return false;
|
||||||
@@ -279,9 +311,9 @@ append_bits :: proc(buf: []byte, u: u64, base: int, neg: bool, digits: string, f
|
|||||||
|
|
||||||
a: [65]byte;
|
a: [65]byte;
|
||||||
i := a.count;
|
i := a.count;
|
||||||
if neg {
|
|
||||||
u = -u;
|
neg: bool;
|
||||||
}
|
u, neg = is_integer_negative(u, is_signed, bit_size);
|
||||||
|
|
||||||
if is_pow2(cast(i64)base) {
|
if is_pow2(cast(i64)base) {
|
||||||
b := cast(u64)base;
|
b := cast(u64)base;
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ String get_fullpath_core(gbAllocator a, String path) {
|
|||||||
void init_build_context(void) {
|
void init_build_context(void) {
|
||||||
BuildContext *bc = &build_context;
|
BuildContext *bc = &build_context;
|
||||||
bc->ODIN_VENDOR = str_lit("odin");
|
bc->ODIN_VENDOR = str_lit("odin");
|
||||||
bc->ODIN_VERSION = str_lit("0.1.1");
|
bc->ODIN_VERSION = str_lit("0.1.2");
|
||||||
bc->ODIN_ROOT = odin_root_dir();
|
bc->ODIN_ROOT = odin_root_dir();
|
||||||
|
|
||||||
#if defined(GB_SYSTEM_WINDOWS)
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
|||||||
@@ -1917,6 +1917,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
|
|||||||
} else {
|
} else {
|
||||||
x->mode = Addressing_Value;
|
x->mode = Addressing_Value;
|
||||||
|
|
||||||
|
|
||||||
update_expr_type(c, x->expr, default_type(x->type), true);
|
update_expr_type(c, x->expr, default_type(x->type), true);
|
||||||
update_expr_type(c, y->expr, default_type(y->type), true);
|
update_expr_type(c, y->expr, default_type(y->type), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2261,22 +2261,18 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
i64 sz = type_size_of(proc->module->allocator, src);
|
i64 sz = type_size_of(proc->module->allocator, src);
|
||||||
i64 dz = type_size_of(proc->module->allocator, dst);
|
i64 dz = type_size_of(proc->module->allocator, dst);
|
||||||
irConvKind kind = irConv_trunc;
|
irConvKind kind = irConv_trunc;
|
||||||
if (dz == sz) {
|
|
||||||
|
if (dz < sz) {
|
||||||
|
kind = irConv_trunc;
|
||||||
|
} else if (dz == sz) {
|
||||||
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
|
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
|
||||||
// NOTE(bill): Copy the value just for type correctness
|
// NOTE(bill): Copy the value just for type correctness
|
||||||
kind = irConv_bitcast;
|
kind = irConv_bitcast;
|
||||||
} else if (dz > sz) {
|
} else if (dz > sz) {
|
||||||
kind = irConv_zext;
|
if (is_type_unsigned(src)) {
|
||||||
|
kind = irConv_zext; // zero extent
|
||||||
// TODO(bill): figure out the rules completely
|
|
||||||
bool ss = !is_type_unsigned(src);
|
|
||||||
bool ds = !is_type_unsigned(dst);
|
|
||||||
if (ss && ds) {
|
|
||||||
kind = irConv_sext;
|
|
||||||
} else if (ss) {
|
|
||||||
kind = irConv_sext;
|
|
||||||
} else {
|
} else {
|
||||||
kind = irConv_zext;
|
kind = irConv_sext; // sign extent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4900,9 +4896,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
|
|
||||||
for_array(i, inits) {
|
for_array(i, inits) {
|
||||||
if (lvals.e[i].addr == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ir_addr_store(proc, lvals.e[i], inits.e[i]);
|
ir_addr_store(proc, lvals.e[i], inits.e[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ extern "C" {
|
|||||||
|
|
||||||
#define USE_CUSTOM_BACKEND false
|
#define USE_CUSTOM_BACKEND false
|
||||||
|
|
||||||
|
|
||||||
#include "common.c"
|
#include "common.c"
|
||||||
#include "timings.c"
|
#include "timings.c"
|
||||||
#include "build_settings.c"
|
#include "build_settings.c"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ typedef struct ssaProc ssaProc;
|
|||||||
typedef struct ssaEdge ssaEdge;
|
typedef struct ssaEdge ssaEdge;
|
||||||
typedef struct ssaRegister ssaRegister;
|
typedef struct ssaRegister ssaRegister;
|
||||||
typedef enum ssaBlockKind ssaBlockKind;
|
typedef enum ssaBlockKind ssaBlockKind;
|
||||||
typedef enum ssaBranchPredicition ssaBranchPredicition;
|
typedef enum ssaBranchPrediction ssaBranchPrediction;
|
||||||
|
|
||||||
String ssa_mangle_name(ssaModule *m, String path, Entity *e);
|
String ssa_mangle_name(ssaModule *m, String path, Entity *e);
|
||||||
|
|
||||||
@@ -22,6 +22,8 @@ enum ssaOp {
|
|||||||
|
|
||||||
ssaOp_Unknown,
|
ssaOp_Unknown,
|
||||||
|
|
||||||
|
ssaOp_Comment, // Does nothing
|
||||||
|
|
||||||
ssaOp_SP, // Stack Pointer
|
ssaOp_SP, // Stack Pointer
|
||||||
ssaOp_SB, // Stack Base
|
ssaOp_SB, // Stack Base
|
||||||
ssaOp_Addr, // Address of something - special rules for certain types when loading and storing (e.g. Maps)
|
ssaOp_Addr, // Address of something - special rules for certain types when loading and storing (e.g. Maps)
|
||||||
@@ -38,6 +40,7 @@ enum ssaOp {
|
|||||||
ssaOp_ArrayIndex, // Index for a fixed array
|
ssaOp_ArrayIndex, // Index for a fixed array
|
||||||
ssaOp_PtrIndex, // Index for a struct/tuple/etc
|
ssaOp_PtrIndex, // Index for a struct/tuple/etc
|
||||||
ssaOp_OffsetPtr,
|
ssaOp_OffsetPtr,
|
||||||
|
ssaOp_ValueIndex, // Extract for a value from a register
|
||||||
|
|
||||||
ssaOp_Phi,
|
ssaOp_Phi,
|
||||||
ssaOp_Copy,
|
ssaOp_Copy,
|
||||||
@@ -309,7 +312,7 @@ enum ssaBlockKind {
|
|||||||
ssaBlock_Count,
|
ssaBlock_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ssaBranchPredicition {
|
enum ssaBranchPrediction {
|
||||||
ssaBranch_Unknown = 0,
|
ssaBranch_Unknown = 0,
|
||||||
ssaBranch_Likely = +1,
|
ssaBranch_Likely = +1,
|
||||||
ssaBranch_Unlikely = -1,
|
ssaBranch_Unlikely = -1,
|
||||||
@@ -332,7 +335,7 @@ struct ssaBlock {
|
|||||||
ssaProc * proc; // Containing procedure
|
ssaProc * proc; // Containing procedure
|
||||||
|
|
||||||
// Likely branch direction
|
// Likely branch direction
|
||||||
ssaBranchPredicition likeliness;
|
ssaBranchPrediction likeliness;
|
||||||
|
|
||||||
ssaValueArray values;
|
ssaValueArray values;
|
||||||
ssaEdgeArray preds;
|
ssaEdgeArray preds;
|
||||||
@@ -428,7 +431,7 @@ void ssa_add_to_edge(ssaBlock *b, ssaBlock *c) {
|
|||||||
ssaEdge s = {c, j};
|
ssaEdge s = {c, j};
|
||||||
ssaEdge p = {b, i};
|
ssaEdge p = {b, i};
|
||||||
array_add(&b->succs, s);
|
array_add(&b->succs, s);
|
||||||
array_add(&b->preds, p);
|
array_add(&c->preds, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -522,6 +525,24 @@ bool ssa_is_blank_ident(AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum ssaAddrKind {
|
||||||
|
ssaAddr_Default,
|
||||||
|
} ssaAddrKind;
|
||||||
|
|
||||||
|
typedef struct ssaAddr {
|
||||||
|
ssaValue * addr;
|
||||||
|
ssaAddrKind kind;
|
||||||
|
} ssaAddr;
|
||||||
|
|
||||||
|
ssaAddr ssa_addr(ssaValue *v) {
|
||||||
|
if (v != NULL) {
|
||||||
|
GB_ASSERT(is_type_pointer(v->type));
|
||||||
|
}
|
||||||
|
ssaAddr addr = {0};
|
||||||
|
addr.addr = v;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ssaProc *ssa_new_proc(ssaModule *m, String name, Entity *entity, DeclInfo *decl_info) {
|
ssaProc *ssa_new_proc(ssaModule *m, String name, Entity *entity, DeclInfo *decl_info) {
|
||||||
@@ -537,7 +558,9 @@ ssaProc *ssa_new_proc(ssaModule *m, String name, Entity *entity, DeclInfo *decl_
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *ssa_add_local(ssaProc *p, Entity *e, AstNode *expr) {
|
ssaAddr ssa_add_local(ssaProc *p, Entity *e, AstNode *expr) {
|
||||||
|
ssaAddr result = {0};
|
||||||
|
|
||||||
Type *t = make_type_pointer(p->module->allocator, e->type);
|
Type *t = make_type_pointer(p->module->allocator, e->type);
|
||||||
ssaValue *local = ssa_new_value0(p->entry, ssaOp_Local, t);
|
ssaValue *local = ssa_new_value0(p->entry, ssaOp_Local, t);
|
||||||
map_ssa_value_set(&p->values, hash_pointer(e), local);
|
map_ssa_value_set(&p->values, hash_pointer(e), local);
|
||||||
@@ -545,18 +568,21 @@ ssaValue *ssa_add_local(ssaProc *p, Entity *e, AstNode *expr) {
|
|||||||
|
|
||||||
ssaValue *addr = ssa_new_value1(p->curr_block, ssaOp_Addr, local->type, local);
|
ssaValue *addr = ssa_new_value1(p->curr_block, ssaOp_Addr, local->type, local);
|
||||||
ssa_new_value1(p->curr_block, ssaOp_Zero, t, addr);
|
ssa_new_value1(p->curr_block, ssaOp_Zero, t, addr);
|
||||||
return addr;
|
result.addr = addr;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
ssaValue *ssa_add_local_for_ident(ssaProc *p, AstNode *name) {
|
ssaAddr ssa_add_local_for_ident(ssaProc *p, AstNode *name) {
|
||||||
|
ssaAddr result = {0};
|
||||||
|
|
||||||
Entity **found = map_entity_get(&p->module->info->definitions, hash_pointer(name));
|
Entity **found = map_entity_get(&p->module->info->definitions, hash_pointer(name));
|
||||||
if (found) {
|
if (found) {
|
||||||
Entity *e = *found;
|
Entity *e = *found;
|
||||||
return ssa_add_local(p, e, name);
|
return ssa_add_local(p, e, name);
|
||||||
}
|
}
|
||||||
return NULL;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *ssa_add_local_generated(ssaProc *p, Type *t) {
|
ssaAddr ssa_add_local_generated(ssaProc *p, Type *t) {
|
||||||
GB_ASSERT(t != NULL);
|
GB_ASSERT(t != NULL);
|
||||||
|
|
||||||
Scope *scope = NULL;
|
Scope *scope = NULL;
|
||||||
@@ -567,8 +593,9 @@ ssaValue *ssa_add_local_generated(ssaProc *p, Type *t) {
|
|||||||
return ssa_add_local(p, e, NULL);
|
return ssa_add_local(p, e, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssa_emit_comment(ssaProc *p, String s) {
|
||||||
|
ssa_new_value0v(p->curr_block, ssaOp_Comment, NULL, exact_value_string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -576,9 +603,14 @@ ssaValue *ssa_add_local_generated(ssaProc *p, Type *t) {
|
|||||||
void ssa_build_stmt(ssaProc *p, AstNode *node);
|
void ssa_build_stmt(ssaProc *p, AstNode *node);
|
||||||
void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes);
|
void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes);
|
||||||
|
|
||||||
|
void ssa_addr_store(ssaProc *p, ssaAddr addr, ssaValue *value) {
|
||||||
|
if (addr.addr == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ssaValue *ssa_build_addr(ssaProc *p, AstNode *node) {
|
ssaAddr ssa_build_addr(ssaProc *p, AstNode *node) {
|
||||||
return NULL;
|
return ssa_addr(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
|
ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
|
||||||
@@ -633,10 +665,6 @@ void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssa_addr_store(ssaProc *p, ssaValue *addr, ssaValue *value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssaValue *ssa_emit_struct_ep(ssaProc *p, ssaValue *ptr, i32 index) {
|
ssaValue *ssa_emit_struct_ep(ssaProc *p, ssaValue *ptr, i32 index) {
|
||||||
GB_ASSERT(ptr->type != NULL);
|
GB_ASSERT(ptr->type != NULL);
|
||||||
@@ -659,6 +687,13 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
|
|||||||
ssa_build_stmt_list(p, bs->stmts);
|
ssa_build_stmt_list(p, bs->stmts);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(us, UsingStmt, node);
|
||||||
|
AstNode *decl = unparen_expr(us->node);
|
||||||
|
if (decl->kind == AstNode_ValueDecl) {
|
||||||
|
ssa_build_stmt(p, decl);
|
||||||
|
}
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(vd, ValueDecl, node);
|
case_ast_node(vd, ValueDecl, node);
|
||||||
if (vd->is_var) {
|
if (vd->is_var) {
|
||||||
ssaModule *m = p->module;
|
ssaModule *m = p->module;
|
||||||
@@ -671,14 +706,14 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ssaValueArray lvals = {0};
|
Array(ssaAddr) lvals = {0};
|
||||||
ssaValueArray inits = {0};
|
ssaValueArray inits = {0};
|
||||||
array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
|
array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
|
||||||
array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
|
array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
|
||||||
|
|
||||||
for_array(i, vd->names) {
|
for_array(i, vd->names) {
|
||||||
AstNode *name = vd->names.e[i];
|
AstNode *name = vd->names.e[i];
|
||||||
ssaValue *lval = NULL;
|
ssaAddr lval = ssa_addr(NULL);
|
||||||
if (!ssa_is_blank_ident(name)) {
|
if (!ssa_is_blank_ident(name)) {
|
||||||
lval = ssa_add_local_for_ident(p, name);
|
lval = ssa_add_local_for_ident(p, name);
|
||||||
}
|
}
|
||||||
@@ -688,11 +723,10 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
|
|||||||
|
|
||||||
for_array(i, vd->values) {
|
for_array(i, vd->values) {
|
||||||
ssaValue *init = ssa_build_expr(p, vd->values.e[i]);
|
ssaValue *init = ssa_build_expr(p, vd->values.e[i]);
|
||||||
if (init == NULL || init->type == NULL) {
|
if (init == NULL) { // TODO(bill): remove this
|
||||||
// TODO(bill): remove this
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Type *t = base_type(init->type);
|
Type *t = type_deref(init->type);
|
||||||
if (init->op == ssaOp_Addr && t->kind == Type_Tuple) {
|
if (init->op == ssaOp_Addr && t->kind == Type_Tuple) {
|
||||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||||
Entity *e = t->Tuple.variables[i];
|
Entity *e = t->Tuple.variables[i];
|
||||||
@@ -704,11 +738,7 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for_array(i, inits) {
|
for_array(i, inits) {
|
||||||
if (lvals.e[i] == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ssa_addr_store(p, lvals.e[i], inits.e[i]);
|
ssa_addr_store(p, lvals.e[i], inits.e[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -716,6 +746,89 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
|
|||||||
gb_temp_arena_memory_end(tmp);
|
gb_temp_arena_memory_end(tmp);
|
||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(as, AssignStmt, node);
|
||||||
|
ssa_emit_comment(p, str_lit("AssignStmt"));
|
||||||
|
|
||||||
|
ssaModule *m = p->module;
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||||
|
|
||||||
|
switch (as->op.kind) {
|
||||||
|
case Token_Eq: {
|
||||||
|
Array(ssaAddr) lvals = {0};
|
||||||
|
array_init(&lvals, m->tmp_allocator);
|
||||||
|
|
||||||
|
for_array(i, as->lhs) {
|
||||||
|
AstNode *lhs = as->lhs.e[i];
|
||||||
|
ssaAddr lval = {0};
|
||||||
|
if (!ssa_is_blank_ident(lhs)) {
|
||||||
|
lval = ssa_build_addr(p, lhs);
|
||||||
|
}
|
||||||
|
array_add(&lvals, lval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (as->lhs.count == as->rhs.count) {
|
||||||
|
if (as->lhs.count == 1) {
|
||||||
|
AstNode *rhs = as->rhs.e[0];
|
||||||
|
ssaValue *init = ssa_build_expr(p, rhs);
|
||||||
|
ssa_addr_store(p, lvals.e[0], init);
|
||||||
|
} else {
|
||||||
|
ssaValueArray inits;
|
||||||
|
array_init_reserve(&inits, m->tmp_allocator, lvals.count);
|
||||||
|
|
||||||
|
for_array(i, as->rhs) {
|
||||||
|
ssaValue *init = ssa_build_expr(p, as->rhs.e[i]);
|
||||||
|
array_add(&inits, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
for_array(i, inits) {
|
||||||
|
ssa_addr_store(p, lvals.e[i], inits.e[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ssaValueArray inits;
|
||||||
|
array_init_reserve(&inits, m->tmp_allocator, lvals.count);
|
||||||
|
|
||||||
|
for_array(i, as->rhs) {
|
||||||
|
ssaValue *init = ssa_build_expr(p, as->rhs.e[i]);
|
||||||
|
Type *t = type_deref(init->type);
|
||||||
|
// TODO(bill): refactor for code reuse as this is repeated a bit
|
||||||
|
if (init->op == ssaOp_Addr && t->kind == Type_Tuple) {
|
||||||
|
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||||
|
Entity *e = t->Tuple.variables[i];
|
||||||
|
ssaValue *v = ssa_emit_struct_ep(p, init, i);
|
||||||
|
array_add(&inits, v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
array_add(&inits, init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for_array(i, inits) {
|
||||||
|
ssa_addr_store(p, lvals.e[i], inits.e[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
GB_PANIC("TODO(bill): assign operations");
|
||||||
|
// NOTE(bill): Only 1 += 1 is allowed, no tuples
|
||||||
|
// +=, -=, etc
|
||||||
|
// i32 op = cast(i32)as->op.kind;
|
||||||
|
// op += Token_Add - Token_AddEq; // Convert += to +
|
||||||
|
// ssaAddr lhs = ssa_build_addr(p, as->lhs.e[0]);
|
||||||
|
// ssaValue *value = ssa_build_expr(p, as->rhs.e[0]);
|
||||||
|
// ssa_build_assign_op(p, lhs, value, cast(TokenKind)op);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_temp_arena_memory_end(tmp);
|
||||||
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(es, ExprStmt, node);
|
||||||
|
// NOTE(bill): No need to use return value
|
||||||
|
ssa_build_expr(p, es->expr);
|
||||||
|
case_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user