Finally fix signed integer conversion and printing

This commit is contained in:
Ginger Bill
2017-03-10 10:34:25 +00:00
parent e2734a2dc6
commit 0fcbda951a
8 changed files with 253 additions and 84 deletions
+1 -1
View File
@@ -209,7 +209,7 @@ String get_fullpath_core(gbAllocator a, String path) {
void init_build_context(void) {
BuildContext *bc = &build_context;
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();
#if defined(GB_SYSTEM_WINDOWS)
+1
View File
@@ -1917,6 +1917,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
} else {
x->mode = Addressing_Value;
update_expr_type(c, x->expr, default_type(x->type), true);
update_expr_type(c, y->expr, default_type(y->type), true);
}
+7 -14
View File
@@ -2261,22 +2261,18 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
i64 sz = type_size_of(proc->module->allocator, src);
i64 dz = type_size_of(proc->module->allocator, dst);
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): Copy the value just for type correctness
kind = irConv_bitcast;
} else if (dz > sz) {
kind = irConv_zext;
// 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;
if (is_type_unsigned(src)) {
kind = irConv_zext; // zero extent
} 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) {
if (lvals.e[i].addr == NULL) {
continue;
}
ir_addr_store(proc, lvals.e[i], inits.e[i]);
}
}
-1
View File
@@ -4,7 +4,6 @@ extern "C" {
#define USE_CUSTOM_BACKEND false
#include "common.c"
#include "timings.c"
#include "build_settings.c"
+140 -27
View File
@@ -6,7 +6,7 @@ typedef struct ssaProc ssaProc;
typedef struct ssaEdge ssaEdge;
typedef struct ssaRegister ssaRegister;
typedef enum ssaBlockKind ssaBlockKind;
typedef enum ssaBranchPredicition ssaBranchPredicition;
typedef enum ssaBranchPrediction ssaBranchPrediction;
String ssa_mangle_name(ssaModule *m, String path, Entity *e);
@@ -22,6 +22,8 @@ enum ssaOp {
ssaOp_Unknown,
ssaOp_Comment, // Does nothing
ssaOp_SP, // Stack Pointer
ssaOp_SB, // Stack Base
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_PtrIndex, // Index for a struct/tuple/etc
ssaOp_OffsetPtr,
ssaOp_ValueIndex, // Extract for a value from a register
ssaOp_Phi,
ssaOp_Copy,
@@ -309,7 +312,7 @@ enum ssaBlockKind {
ssaBlock_Count,
};
enum ssaBranchPredicition {
enum ssaBranchPrediction {
ssaBranch_Unknown = 0,
ssaBranch_Likely = +1,
ssaBranch_Unlikely = -1,
@@ -332,7 +335,7 @@ struct ssaBlock {
ssaProc * proc; // Containing procedure
// Likely branch direction
ssaBranchPredicition likeliness;
ssaBranchPrediction likeliness;
ssaValueArray values;
ssaEdgeArray preds;
@@ -428,7 +431,7 @@ void ssa_add_to_edge(ssaBlock *b, ssaBlock *c) {
ssaEdge s = {c, j};
ssaEdge p = {b, i};
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) {
@@ -537,7 +558,9 @@ ssaProc *ssa_new_proc(ssaModule *m, String name, Entity *entity, DeclInfo *decl_
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);
ssaValue *local = ssa_new_value0(p->entry, ssaOp_Local, t);
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);
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));
if (found) {
Entity *e = *found;
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);
Scope *scope = NULL;
@@ -567,8 +593,9 @@ ssaValue *ssa_add_local_generated(ssaProc *p, Type *t) {
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_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) {
return NULL;
ssaAddr ssa_build_addr(ssaProc *p, AstNode *node) {
return ssa_addr(NULL);
}
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) {
GB_ASSERT(ptr->type != NULL);
@@ -659,6 +687,13 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
ssa_build_stmt_list(p, bs->stmts);
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);
if (vd->is_var) {
ssaModule *m = p->module;
@@ -671,14 +706,14 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
}
}
} else {
ssaValueArray lvals = {0};
ssaValueArray inits = {0};
Array(ssaAddr) lvals = {0};
ssaValueArray inits = {0};
array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
for_array(i, vd->names) {
AstNode *name = vd->names.e[i];
ssaValue *lval = NULL;
ssaAddr lval = ssa_addr(NULL);
if (!ssa_is_blank_ident(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) {
ssaValue *init = ssa_build_expr(p, vd->values.e[i]);
if (init == NULL || init->type == NULL) {
// TODO(bill): remove this
if (init == NULL) { // TODO(bill): remove this
continue;
}
Type *t = base_type(init->type);
Type *t = type_deref(init->type);
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];
@@ -704,11 +738,7 @@ void ssa_build_stmt(ssaProc *p, AstNode *node) {
}
}
for_array(i, inits) {
if (lvals.e[i] == NULL) {
continue;
}
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);
}
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;
}
}