mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Variable declaration and assign, unary operators
This commit is contained in:
+15
-11
@@ -1,16 +1,20 @@
|
|||||||
define void @main() {
|
define void @main() {
|
||||||
entry:
|
entry:
|
||||||
%0 = alloca i64, align 8
|
%0 = alloca i64, align 8 ; a
|
||||||
store i64 zeroinitializer, i64* %0
|
store i64 zeroinitializer, i64* %0
|
||||||
store i64 137, i64* %0
|
%1 = alloca i64, align 8 ; b
|
||||||
%1 = load i64, i64* %0
|
store i64 zeroinitializer, i64* %1
|
||||||
add i64 1, %1
|
store i64 1, i64* %0
|
||||||
store i64 %2, i64* %0
|
store i64 2, i64* %1
|
||||||
%3 = alloca float, align 4
|
%2 = load i64, i64* %0
|
||||||
store float zeroinitializer, float* %3
|
%3 = add i64 %2, 1
|
||||||
store float 0x3f8147ae00000000, float* %3
|
store i64 %3, i64* %0
|
||||||
%4 = load float, float* %3
|
%4 = load i64, i64* %1
|
||||||
fadd float %4, 0x3f7d70a400000000
|
%5 = add i64 %4, 1
|
||||||
store float %5, float* %3
|
store i64 %5, i64* %1
|
||||||
|
%6 = load i64, i64* %1
|
||||||
|
%7 = load i64, i64* %0
|
||||||
|
%8 = add i64 %7, %6
|
||||||
|
store i64 %8, i64* %0
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-9
@@ -1,11 +1,6 @@
|
|||||||
main :: proc() {
|
main :: proc() {
|
||||||
// x : string;
|
a, b := 1, 2;
|
||||||
// x = "Hello";
|
a++;
|
||||||
x : int;
|
b++;
|
||||||
x = 137;
|
a += b;
|
||||||
x = 1 + x;
|
|
||||||
|
|
||||||
y : f32;
|
|
||||||
y = 1.01;
|
|
||||||
y = y + 0.99;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -631,7 +631,7 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
|
|||||||
error(&c->error_collector, op, "Assignment operation `%.*s` requires single-valued expressions", LIT(op.string));
|
error(&c->error_collector, op, "Assignment operation `%.*s` requires single-valued expressions", LIT(op.string));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!gb_is_between(op.kind, Token_AddEq, Token_ModEq)) {
|
if (!gb_is_between(op.kind, Token__AssignOpBegin+1, Token__AssignOpEnd-1)) {
|
||||||
error(&c->error_collector, op, "Unknown Assignment operation `%.*s`", LIT(op.string));
|
error(&c->error_collector, op, "Unknown Assignment operation `%.*s`", LIT(op.string));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,12 @@ Type *make_type_procedure(gbAllocator a, Scope *scope, Type *params, isize param
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type *type_deref(Type *t) {
|
||||||
|
if (t != NULL && t->kind == Type_Pointer)
|
||||||
|
return t->pointer.element;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
||||||
gb_global Type basic_types[] = {
|
gb_global Type basic_types[] = {
|
||||||
|
|||||||
+11
-8
@@ -146,7 +146,7 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) {
|
|||||||
if (i > 0) ssa_fprintf(f, ", ");
|
if (i > 0) ssa_fprintf(f, ", ");
|
||||||
ssa_print_type(f, s, &t->procedure.params[i]);
|
ssa_print_type(f, s, &t->procedure.params[i]);
|
||||||
}
|
}
|
||||||
ssa_fprintf(f, ")");
|
ssa_fprintf(f, ") ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type
|
|||||||
case ExactValue_String: {
|
case ExactValue_String: {
|
||||||
ssa_fprintf(f, "{");
|
ssa_fprintf(f, "{");
|
||||||
ssa_print_type(f, m->sizes, &basic_types[Basic_i8]);
|
ssa_print_type(f, m->sizes, &basic_types[Basic_i8]);
|
||||||
ssa_fprintf(f, "* \"");
|
ssa_fprintf(f, "* c\"");
|
||||||
// TODO(bill): Make unquote string function
|
// TODO(bill): Make unquote string function
|
||||||
String unquoted = value.value_string;
|
String unquoted = value.value_string;
|
||||||
unquoted.text++;
|
unquoted.text++;
|
||||||
@@ -209,7 +209,7 @@ void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint)
|
|||||||
}
|
}
|
||||||
switch (value->kind) {
|
switch (value->kind) {
|
||||||
case ssaValue_TypeName:
|
case ssaValue_TypeName:
|
||||||
ssa_print_encoded_local(f, value->type_name->token.string);
|
ssa_print_encoded_local(f, value->type_name.entity->token.string);
|
||||||
break;
|
break;
|
||||||
case ssaValue_Global:
|
case ssaValue_Global:
|
||||||
ssa_print_encoded_global(f, value->global.entity->token.string);
|
ssa_print_encoded_global(f, value->global.entity->token.string);
|
||||||
@@ -237,7 +237,9 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
Type *type = instr->local.entity->type;
|
Type *type = instr->local.entity->type;
|
||||||
ssa_fprintf(f, "%%%d = alloca ", value->id);
|
ssa_fprintf(f, "%%%d = alloca ", value->id);
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, ", align %lld\n", type_align_of(m->sizes, gb_heap_allocator(), type));
|
ssa_fprintf(f, ", align %lld ", type_align_of(m->sizes, gb_heap_allocator(), type));
|
||||||
|
ssa_fprintf(f, "; %.*s", LIT(instr->local.entity->token.string));
|
||||||
|
ssa_fprintf(f, "\n");
|
||||||
ssa_fprintf(f, "\tstore ");
|
ssa_fprintf(f, "\tstore ");
|
||||||
ssa_print_type(f, m->sizes, type);
|
ssa_print_type(f, m->sizes, type);
|
||||||
ssa_fprintf(f, " zeroinitializer, ");
|
ssa_fprintf(f, " zeroinitializer, ");
|
||||||
@@ -271,9 +273,11 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
|
|
||||||
|
|
||||||
case ssaInstruction_BinaryOp: {
|
case ssaInstruction_BinaryOp: {
|
||||||
ssaBinaryOp *bo = &value->instruction.binary_op;
|
auto *bo = &value->instruction.binary_op;
|
||||||
Type *type = ssa_value_type(bo->left);
|
Type *type = ssa_value_type(bo->left);
|
||||||
|
|
||||||
|
ssa_fprintf(f, "%%%d = ", value->id);
|
||||||
|
|
||||||
if (is_type_float(type))
|
if (is_type_float(type))
|
||||||
ssa_fprintf(f, "f");
|
ssa_fprintf(f, "f");
|
||||||
|
|
||||||
@@ -320,15 +324,14 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
|
void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
|
||||||
gb_printf("-- Printing LLVM-IR -- \n\n");
|
|
||||||
gb_for_array(member_index, m->members.entries) {
|
gb_for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries[member_index];
|
auto *entry = &m->members.entries[member_index];
|
||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
switch (v->kind) {
|
switch (v->kind) {
|
||||||
case ssaValue_TypeName: {
|
case ssaValue_TypeName: {
|
||||||
ssa_print_encoded_local(f, v->type_name->token.string);
|
ssa_print_encoded_local(f, v->type_name.entity->token.string);
|
||||||
ssa_fprintf(f, " = type ");
|
ssa_fprintf(f, " = type ");
|
||||||
ssa_print_type(f, m->sizes, get_base_type(v->type_name->type));
|
ssa_print_type(f, m->sizes, get_base_type(v->type_name.type));
|
||||||
ssa_fprintf(f, "\n");
|
ssa_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+227
-57
@@ -30,41 +30,35 @@ struct ssaProcedure {
|
|||||||
ssaModule *module;
|
ssaModule *module;
|
||||||
String name;
|
String name;
|
||||||
Entity *entity;
|
Entity *entity;
|
||||||
|
Type *type;
|
||||||
DeclarationInfo *decl;
|
DeclarationInfo *decl;
|
||||||
AstNode *type_expr;
|
AstNode *type_expr;
|
||||||
AstNode *body;
|
AstNode *body;
|
||||||
|
|
||||||
gbArray(ssaValue *) blocks;
|
gbArray(ssaValue *) blocks;
|
||||||
ssaBlock *curr_block;
|
ssaBlock *curr_block;
|
||||||
|
gbArray(ssaValue *) anonymous_procedures;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ssaLocal {
|
|
||||||
|
struct ssaTypeName {
|
||||||
Entity *entity;
|
Entity *entity;
|
||||||
|
Type *type;
|
||||||
};
|
};
|
||||||
struct ssaGlobal {
|
struct ssaGlobal {
|
||||||
b32 generated;
|
b32 generated;
|
||||||
Entity *entity;
|
Entity *entity;
|
||||||
|
Type *type;
|
||||||
ssaValue *value;
|
ssaValue *value;
|
||||||
};
|
};
|
||||||
struct ssaStore {
|
struct ssaConstant {
|
||||||
ssaValue *address;
|
Type *type;
|
||||||
ssaValue *value;
|
ExactValue value;
|
||||||
};
|
|
||||||
struct ssaLoad {
|
|
||||||
ssaValue *address;
|
|
||||||
};
|
|
||||||
struct ssaBinaryOp {
|
|
||||||
Token op;
|
|
||||||
ssaValue *left, *right;
|
|
||||||
};
|
|
||||||
struct ssaGetElementPtr {
|
|
||||||
ssaValue *address;
|
|
||||||
Type *result_type;
|
|
||||||
Type *element_type;
|
|
||||||
gbArray(ssaValue *) indices;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum ssaInstructionKind {
|
enum ssaInstructionKind {
|
||||||
ssaInstruction_Invalid,
|
ssaInstruction_Invalid,
|
||||||
|
|
||||||
@@ -73,6 +67,8 @@ enum ssaInstructionKind {
|
|||||||
ssaInstruction_Load,
|
ssaInstruction_Load,
|
||||||
ssaInstruction_GetElementPtr,
|
ssaInstruction_GetElementPtr,
|
||||||
|
|
||||||
|
ssaInstruction_Convert,
|
||||||
|
|
||||||
ssaInstruction_BinaryOp,
|
ssaInstruction_BinaryOp,
|
||||||
|
|
||||||
ssaInstruction_Count,
|
ssaInstruction_Count,
|
||||||
@@ -86,12 +82,31 @@ struct ssaInstruction {
|
|||||||
TokenPos pos;
|
TokenPos pos;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
ssaLocal local;
|
struct {
|
||||||
ssaStore store;
|
Entity *entity;
|
||||||
ssaLoad load;
|
Type *type;
|
||||||
ssaGetElementPtr get_element_ptr;
|
} local;
|
||||||
|
struct {
|
||||||
|
ssaValue *address;
|
||||||
|
ssaValue *value;
|
||||||
|
} store;
|
||||||
|
struct {
|
||||||
|
ssaValue *address;
|
||||||
|
} load;
|
||||||
|
struct {
|
||||||
|
ssaValue *address;
|
||||||
|
Type *result_type;
|
||||||
|
Type *element_type;
|
||||||
|
isize index_count;
|
||||||
|
isize indices[2];
|
||||||
|
} get_element_ptr;
|
||||||
|
|
||||||
ssaBinaryOp binary_op;
|
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Token op;
|
||||||
|
ssaValue *left, *right;
|
||||||
|
} binary_op;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,10 +130,10 @@ struct ssaValue {
|
|||||||
i32 id;
|
i32 id;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
Entity * type_name;
|
ssaTypeName type_name;
|
||||||
ssaGlobal global;
|
ssaGlobal global;
|
||||||
ssaProcedure procedure;
|
ssaProcedure procedure;
|
||||||
TypeAndValue constant;
|
ssaConstant constant;
|
||||||
ssaBlock block;
|
ssaBlock block;
|
||||||
ssaInstruction instruction;
|
ssaInstruction instruction;
|
||||||
};
|
};
|
||||||
@@ -162,11 +177,12 @@ void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) {
|
|||||||
|
|
||||||
|
|
||||||
Type *ssa_value_type(ssaValue *value);
|
Type *ssa_value_type(ssaValue *value);
|
||||||
|
void ssa_value_set_type(ssaValue *value, Type *type);
|
||||||
|
|
||||||
Type *ssa_instruction_type(ssaInstruction *instr) {
|
Type *ssa_instruction_type(ssaInstruction *instr) {
|
||||||
switch (instr->kind) {
|
switch (instr->kind) {
|
||||||
case ssaInstruction_Local:
|
case ssaInstruction_Local:
|
||||||
return instr->local.entity->type;
|
return instr->local.type;
|
||||||
case ssaInstruction_Store:
|
case ssaInstruction_Store:
|
||||||
return ssa_value_type(instr->store.address);
|
return ssa_value_type(instr->store.address);
|
||||||
case ssaInstruction_Load:
|
case ssaInstruction_Load:
|
||||||
@@ -175,14 +191,28 @@ Type *ssa_instruction_type(ssaInstruction *instr) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssa_instruction_set_type(ssaInstruction *instr, Type *type) {
|
||||||
|
switch (instr->kind) {
|
||||||
|
case ssaInstruction_Local:
|
||||||
|
instr->local.type = type;
|
||||||
|
break;
|
||||||
|
case ssaInstruction_Store:
|
||||||
|
ssa_value_set_type(instr->store.value, type);
|
||||||
|
break;
|
||||||
|
case ssaInstruction_Load:
|
||||||
|
// NOTE(bill): Do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Type *ssa_value_type(ssaValue *value) {
|
Type *ssa_value_type(ssaValue *value) {
|
||||||
switch (value->kind) {
|
switch (value->kind) {
|
||||||
case ssaValue_TypeName:
|
case ssaValue_TypeName:
|
||||||
return value->type_name->type;
|
return value->type_name.type;
|
||||||
case ssaValue_Global:
|
case ssaValue_Global:
|
||||||
return value->global.entity->type;
|
return value->global.type;
|
||||||
case ssaValue_Procedure:
|
case ssaValue_Procedure:
|
||||||
return value->procedure.entity->type;
|
return value->procedure.type;
|
||||||
case ssaValue_Constant:
|
case ssaValue_Constant:
|
||||||
return value->constant.type;
|
return value->constant.type;
|
||||||
case ssaValue_Instruction:
|
case ssaValue_Instruction:
|
||||||
@@ -192,9 +222,32 @@ Type *ssa_value_type(ssaValue *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ssa_value_set_type(ssaValue *value, Type *type) {
|
||||||
|
switch (value->kind) {
|
||||||
|
case ssaValue_TypeName:
|
||||||
|
value->type_name.type = type;
|
||||||
|
break;
|
||||||
|
case ssaValue_Global:
|
||||||
|
value->global.type = type;
|
||||||
|
break;
|
||||||
|
case ssaValue_Procedure:
|
||||||
|
value->procedure.type = type;
|
||||||
|
break;
|
||||||
|
case ssaValue_Constant:
|
||||||
|
value->constant.type = type;
|
||||||
|
break;
|
||||||
|
case ssaValue_Instruction:
|
||||||
|
ssa_instruction_set_type(&value->instruction, type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ssaValue *ssa_build_expression(ssaProcedure *proc, AstNode *expr);
|
||||||
|
ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv);
|
||||||
|
ssaLvalue ssa_build_address(ssaProcedure *proc, AstNode *expr);
|
||||||
|
ssaValue *ssa_emit_conversion(ssaProcedure *proc, ssaValue *value, Type *a_type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -215,14 +268,16 @@ ssaValue *ssa_alloc_instruction(gbAllocator a, ssaInstructionKind kind) {
|
|||||||
|
|
||||||
ssaValue *ssa_make_value_type_name(gbAllocator a, Entity *e) {
|
ssaValue *ssa_make_value_type_name(gbAllocator a, Entity *e) {
|
||||||
ssaValue *v = ssa_alloc_value(a, ssaValue_TypeName);
|
ssaValue *v = ssa_alloc_value(a, ssaValue_TypeName);
|
||||||
v->type_name = e;
|
v->type_name.entity = e;
|
||||||
|
v->type_name.type = e->type;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value) {
|
ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value) {
|
||||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Global);
|
ssaValue *v = ssa_alloc_value(a, ssaValue_Global);
|
||||||
v->global.entity = e;
|
v->global.entity = e;
|
||||||
v->global.value = value;
|
v->global.type = e->type;
|
||||||
|
v->global.value = value;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +287,7 @@ ssaValue *ssa_make_instruction_local(ssaProcedure *p, Entity *e) {
|
|||||||
ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_Local);
|
ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_Local);
|
||||||
ssaInstruction *i = &v->instruction;
|
ssaInstruction *i = &v->instruction;
|
||||||
i->local.entity = e;
|
i->local.entity = e;
|
||||||
|
i->local.type = e->type;
|
||||||
if (p->curr_block) {
|
if (p->curr_block) {
|
||||||
gb_array_append(p->curr_block->values, v);
|
gb_array_append(p->curr_block->values, v);
|
||||||
}
|
}
|
||||||
@@ -295,6 +351,7 @@ ssaValue *ssa_make_value_procedure(gbAllocator a, Entity *e, DeclarationInfo *de
|
|||||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Procedure);
|
ssaValue *v = ssa_alloc_value(a, ssaValue_Procedure);
|
||||||
v->procedure.module = m;
|
v->procedure.module = m;
|
||||||
v->procedure.entity = e;
|
v->procedure.entity = e;
|
||||||
|
v->procedure.type = e->type;
|
||||||
v->procedure.decl = decl;
|
v->procedure.decl = decl;
|
||||||
v->procedure.name = e->token.string;
|
v->procedure.name = e->token.string;
|
||||||
return v;
|
return v;
|
||||||
@@ -302,9 +359,9 @@ ssaValue *ssa_make_value_procedure(gbAllocator a, Entity *e, DeclarationInfo *de
|
|||||||
|
|
||||||
ssaValue *ssa_make_value_block(gbAllocator a, ssaProcedure *proc, AstNode *node, Scope *scope, String label) {
|
ssaValue *ssa_make_value_block(gbAllocator a, ssaProcedure *proc, AstNode *node, Scope *scope, String label) {
|
||||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Block);
|
ssaValue *v = ssa_alloc_value(a, ssaValue_Block);
|
||||||
v->block.label = label;
|
v->block.label = label;
|
||||||
v->block.node = node;
|
v->block.node = node;
|
||||||
v->block.scope = scope;
|
v->block.scope = scope;
|
||||||
v->block.parent = proc;
|
v->block.parent = proc;
|
||||||
|
|
||||||
gb_array_init(v->block.instructions, gb_heap_allocator());
|
gb_array_init(v->block.instructions, gb_heap_allocator());
|
||||||
@@ -421,6 +478,8 @@ ssaValue *ssa_emit_store(ssaProcedure *p, ssaValue *address, ssaValue *value) {
|
|||||||
|
|
||||||
ssaValue *ssa_emit_load(ssaProcedure *p, ssaValue *address) {
|
ssaValue *ssa_emit_load(ssaProcedure *p, ssaValue *address) {
|
||||||
ssaValue *v = ssa_make_instruction_load(p, address);
|
ssaValue *v = ssa_make_instruction_load(p, address);
|
||||||
|
Type *t = ssa_value_type(address);
|
||||||
|
ssa_value_set_type(v, type_deref(t));
|
||||||
ssa_emit(p, v);
|
ssa_emit(p, v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -452,22 +511,28 @@ ssaValue *ssa_lvalue_address(ssaLvalue lval, ssaProcedure *p) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *ssa_build_expression(ssaProcedure *proc, AstNode *expr);
|
Type *ssa_lvalue_type(ssaLvalue lval) {
|
||||||
ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv);
|
switch (lval.kind) {
|
||||||
|
case ssaLvalue_Address:
|
||||||
|
return type_deref(ssa_value_type(lval.address.value));
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ssaValue *ssa_emit_conversion(ssaProcedure *proc, ssaValue *value, Type *a_type) {
|
ssaValue *ssa_emit_conversion(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||||
Type *b_type = ssa_value_type(value);
|
Type *src_type = ssa_value_type(value);
|
||||||
if (are_types_identical(a_type, b_type))
|
if (are_types_identical(t, src_type))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
Type *a = get_base_type(a_type);
|
Type *dst = get_base_type(t);
|
||||||
Type *b = get_base_type(b_type);
|
Type *src = get_base_type(src_type);
|
||||||
|
|
||||||
if (value->kind == ssaValue_Constant) {
|
if (value->kind == ssaValue_Constant) {
|
||||||
if (a->kind == Type_Basic)
|
if (dst->kind == Type_Basic)
|
||||||
return ssa_make_value_constant(proc->module->allocator, a_type, value->constant.value);
|
return ssa_make_value_constant(proc->module->allocator, t, value->constant.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GB_PANIC("TODO(bill): ssa_emit_conversion");
|
GB_PANIC("TODO(bill): ssa_emit_conversion");
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -508,19 +573,36 @@ ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAnd
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case AstNode_DereferenceExpression: {
|
||||||
|
ssaLvalue addr = ssa_build_address(proc, expr->dereference_expression.operand);
|
||||||
|
return ssa_lvalue_load(addr, proc);
|
||||||
|
} break;
|
||||||
|
|
||||||
case AstNode_UnaryExpression: {
|
case AstNode_UnaryExpression: {
|
||||||
auto *ue = &expr->unary_expression;
|
auto *ue = &expr->unary_expression;
|
||||||
switch (ue->op.kind) {
|
switch (ue->op.kind) {
|
||||||
|
case Token_Pointer:
|
||||||
|
return ssa_lvalue_address(ssa_build_address(proc, ue->operand), proc);
|
||||||
case Token_Add:
|
case Token_Add:
|
||||||
return ssa_build_expression(proc, ue->operand);
|
return ssa_build_expression(proc, ue->operand);
|
||||||
case Token_Sub:
|
case Token_Sub: {
|
||||||
return NULL;
|
// NOTE(bill): -x == 0 - x
|
||||||
case Token_Xor:
|
ExactValue zero = make_exact_value_integer(0);
|
||||||
return NULL;
|
ssaValue *left = ssa_make_value_constant(proc->module->allocator, tv->type, zero);
|
||||||
case Token_Not:
|
ssaValue *right = ssa_build_expression(proc, ue->operand);
|
||||||
return NULL;
|
return ssa_emit_arith(proc, ue->op, left, right, tv->type);
|
||||||
case Token_Pointer:
|
} break;
|
||||||
|
case Token_Xor: { // Bitwise not
|
||||||
|
// NOTE(bill): "not" x == x "xor" -1
|
||||||
|
ExactValue neg_one = make_exact_value_integer(-1);
|
||||||
|
ssaValue *left = ssa_build_expression(proc, ue->operand);
|
||||||
|
ssaValue *right = ssa_make_value_constant(proc->module->allocator, tv->type, neg_one);
|
||||||
|
return ssa_emit_arith(proc, ue->op, left, right, tv->type);
|
||||||
|
} break;
|
||||||
|
case Token_Not: // Boolean not
|
||||||
|
GB_PANIC("Token_Not");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -550,8 +632,9 @@ ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAnd
|
|||||||
break;
|
break;
|
||||||
case AstNode_SliceExpression:
|
case AstNode_SliceExpression:
|
||||||
break;
|
break;
|
||||||
case AstNode_IndexExpression:
|
case AstNode_IndexExpression: {
|
||||||
break;
|
|
||||||
|
} break;
|
||||||
case AstNode_SelectorExpression:
|
case AstNode_SelectorExpression:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -609,7 +692,8 @@ ssaLvalue ssa_build_address(ssaProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
case AstNode_DereferenceExpression: {
|
case AstNode_DereferenceExpression: {
|
||||||
ssaLvalue val = {ssaLvalue_Address};
|
ssaLvalue val = {ssaLvalue_Address};
|
||||||
val.address.value = ssa_build_expression(proc, expr);
|
AstNode *operand = expr->dereference_expression.operand;
|
||||||
|
val.address.value = ssa_build_expression(proc, operand);
|
||||||
val.address.expr = expr;
|
val.address.expr = expr;
|
||||||
return val;
|
return val;
|
||||||
} break;
|
} break;
|
||||||
@@ -623,10 +707,20 @@ ssaLvalue ssa_build_address(ssaProcedure *proc, AstNode *expr) {
|
|||||||
// TODO(bill): Others address
|
// TODO(bill): Others address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GB_PANIC("Unexpected address expression");
|
||||||
|
|
||||||
ssaLvalue blank = {ssaLvalue_Blank};
|
ssaLvalue blank = {ssaLvalue_Blank};
|
||||||
return blank;
|
return blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssa_build_assign_op(ssaProcedure *proc, ssaLvalue lhs, ssaValue *value, Token op) {
|
||||||
|
ssaValue *old_value = ssa_lvalue_load(lhs, proc);
|
||||||
|
ssaValue *change = ssa_emit_conversion(proc, value, ssa_value_type(old_value));
|
||||||
|
ssaValue *new_value = ssa_emit_arith(proc, op, old_value, change, ssa_lvalue_type(lhs));
|
||||||
|
ssa_lvalue_store(lhs, proc, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ssa_build_statement(ssaProcedure *proc, AstNode *s);
|
void ssa_build_statement(ssaProcedure *proc, AstNode *s);
|
||||||
|
|
||||||
void ssa_build_statement_list(ssaProcedure *proc, AstNode *list) {
|
void ssa_build_statement_list(ssaProcedure *proc, AstNode *list) {
|
||||||
@@ -642,6 +736,32 @@ void ssa_build_statement(ssaProcedure *proc, AstNode *s) {
|
|||||||
auto *vd = &s->variable_declaration;
|
auto *vd = &s->variable_declaration;
|
||||||
if (vd->kind == Declaration_Mutable) {
|
if (vd->kind == Declaration_Mutable) {
|
||||||
if (vd->name_count == vd->value_count) { // 1:1 assigment
|
if (vd->name_count == vd->value_count) { // 1:1 assigment
|
||||||
|
gbArray(ssaLvalue) lvals;
|
||||||
|
gbArray(ssaValue *) inits;
|
||||||
|
gb_array_init_reserve(lvals, gb_heap_allocator(), vd->name_count);
|
||||||
|
gb_array_init_reserve(inits, gb_heap_allocator(), vd->name_count);
|
||||||
|
defer (gb_array_free(lvals));
|
||||||
|
defer (gb_array_free(inits));
|
||||||
|
|
||||||
|
for (AstNode *name = vd->name_list; name != NULL; name = name->next) {
|
||||||
|
ssaLvalue lval = {ssaLvalue_Blank};
|
||||||
|
if (!ssa_is_blank_identifier(name)) {
|
||||||
|
ssa_add_local_for_identifier(proc, name);
|
||||||
|
lval = ssa_build_address(proc, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_array_append(lvals, lval);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AstNode *value = vd->value_list; value != NULL; value = value->next) {
|
||||||
|
ssaValue *init = ssa_build_expression(proc, value);
|
||||||
|
gb_array_append(inits, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb_for_array(i, inits) {
|
||||||
|
ssa_lvalue_store(lvals[i], proc, inits[i]);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (vd->value_count == 0) { // declared and zero-initialized
|
} else if (vd->value_count == 0) { // declared and zero-initialized
|
||||||
for (AstNode *name = vd->name_list; name != NULL; name = name->next) {
|
for (AstNode *name = vd->name_list; name != NULL; name = name->next) {
|
||||||
@@ -656,6 +776,20 @@ void ssa_build_statement(ssaProcedure *proc, AstNode *s) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case AstNode_IncDecStatement: {
|
||||||
|
Token op = s->inc_dec_statement.op;
|
||||||
|
if (op.kind == Token_Increment) {
|
||||||
|
op.kind = Token_Add;
|
||||||
|
} else if (op.kind == Token_Decrement) {
|
||||||
|
op.kind = Token_Sub;
|
||||||
|
}
|
||||||
|
ssaLvalue lval = ssa_build_address(proc, s->inc_dec_statement.expression);
|
||||||
|
ssaValue *one = ssa_make_value_constant(proc->module->allocator, ssa_lvalue_type(lval),
|
||||||
|
make_exact_value_integer(1));
|
||||||
|
ssa_build_assign_op(proc, lval, one, op);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
case AstNode_AssignStatement: {
|
case AstNode_AssignStatement: {
|
||||||
auto *assign = &s->assign_statement;
|
auto *assign = &s->assign_statement;
|
||||||
switch (assign->op.kind) {
|
switch (assign->op.kind) {
|
||||||
@@ -681,16 +815,36 @@ void ssa_build_statement(ssaProcedure *proc, AstNode *s) {
|
|||||||
ssaValue *init = ssa_build_expression(proc, rhs);
|
ssaValue *init = ssa_build_expression(proc, rhs);
|
||||||
ssa_lvalue_store(lvals[0], proc, init);
|
ssa_lvalue_store(lvals[0], proc, init);
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("TODO(bill): parallel assignment");
|
gbArray(ssaValue *) inits;
|
||||||
|
gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals));
|
||||||
|
defer (gb_array_free(inits));
|
||||||
|
|
||||||
|
for (AstNode *rhs = assign->rhs_list; rhs != NULL; rhs = rhs->next) {
|
||||||
|
ssaValue *init = ssa_build_expression(proc, rhs);
|
||||||
|
gb_array_append(inits, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_for_array(i, inits) {
|
||||||
|
ssa_lvalue_store(lvals[i], proc, inits[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("TODO(bill): tuple assignment");
|
GB_PANIC("TODO(bill): tuple assignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: // +=, -=, etc
|
default: {
|
||||||
break;
|
// NOTE(bill): Only 1 += 1 is allowed, no tuples
|
||||||
|
// +=, -=, etc
|
||||||
|
Token op = assign->op;
|
||||||
|
i32 kind = op.kind;
|
||||||
|
kind += Token_Add - Token_AddEq; // Convert += to +
|
||||||
|
op.kind = cast(TokenKind)kind;
|
||||||
|
ssaLvalue lhs = ssa_build_address(proc, assign->lhs_list);
|
||||||
|
ssaValue *value = ssa_build_expression(proc, assign->rhs_list);
|
||||||
|
ssa_build_assign_op(proc, lhs, value, op);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -701,6 +855,22 @@ void ssa_build_statement(ssaProcedure *proc, AstNode *s) {
|
|||||||
case AstNode_BlockStatement:
|
case AstNode_BlockStatement:
|
||||||
ssa_build_statement_list(proc, s->block_statement.list);
|
ssa_build_statement_list(proc, s->block_statement.list);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AstNode_IfStatement:
|
||||||
|
GB_PANIC("AstNode_IfStatement");
|
||||||
|
break;
|
||||||
|
case AstNode_ReturnStatement:
|
||||||
|
GB_PANIC("AstNode_ReturnStatement");
|
||||||
|
break;
|
||||||
|
case AstNode_ForStatement:
|
||||||
|
GB_PANIC("AstNode_ForStatement");
|
||||||
|
break;
|
||||||
|
case AstNode_DeferStatement:
|
||||||
|
GB_PANIC("AstNode_DeferStatement");
|
||||||
|
break;
|
||||||
|
case AstNode_BranchStatement:
|
||||||
|
GB_PANIC("AstNode_BranchStatement");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +879,7 @@ void ssa_build_statement(ssaProcedure *proc, AstNode *s) {
|
|||||||
void ssa_build_procedure(ssaValue *value) {
|
void ssa_build_procedure(ssaValue *value) {
|
||||||
ssaProcedure *proc = &value->procedure;
|
ssaProcedure *proc = &value->procedure;
|
||||||
|
|
||||||
gb_printf("Building %.*s: %.*s\n", LIT(entity_strings[proc->entity->kind]), LIT(proc->name));
|
// gb_printf("Building %.*s: %.*s\n", LIT(entity_strings[proc->entity->kind]), LIT(proc->name));
|
||||||
|
|
||||||
|
|
||||||
AstNode *proc_decl = proc->decl->proc_decl;
|
AstNode *proc_decl = proc->decl->proc_decl;
|
||||||
|
|||||||
+9
-7
@@ -48,25 +48,29 @@ TOKEN_KIND(_OperatorBegin, "_OperatorBegin"), \
|
|||||||
TOKEN_KIND(Mul, "*"), \
|
TOKEN_KIND(Mul, "*"), \
|
||||||
TOKEN_KIND(Quo, "/"), \
|
TOKEN_KIND(Quo, "/"), \
|
||||||
TOKEN_KIND(Mod, "%"), \
|
TOKEN_KIND(Mod, "%"), \
|
||||||
|
TOKEN_KIND(And, "&"), \
|
||||||
|
TOKEN_KIND(Or, "|"), \
|
||||||
|
TOKEN_KIND(Xor, "~"), \
|
||||||
|
TOKEN_KIND(AndNot, "&~"), \
|
||||||
|
TOKEN_KIND(_AssignOpBegin, "_AssignOpBegin"), \
|
||||||
TOKEN_KIND(AddEq, "+="), \
|
TOKEN_KIND(AddEq, "+="), \
|
||||||
TOKEN_KIND(SubEq, "-="), \
|
TOKEN_KIND(SubEq, "-="), \
|
||||||
TOKEN_KIND(MulEq, "*="), \
|
TOKEN_KIND(MulEq, "*="), \
|
||||||
TOKEN_KIND(QuoEq, "/="), \
|
TOKEN_KIND(QuoEq, "/="), \
|
||||||
TOKEN_KIND(ModEq, "%="), \
|
TOKEN_KIND(ModEq, "%="), \
|
||||||
TOKEN_KIND(And, "&"), \
|
|
||||||
TOKEN_KIND(Or, "|"), \
|
|
||||||
TOKEN_KIND(Xor, "~"), \
|
|
||||||
TOKEN_KIND(AndNot, "&~"), \
|
|
||||||
TOKEN_KIND(AndEq, "&="), \
|
TOKEN_KIND(AndEq, "&="), \
|
||||||
TOKEN_KIND(OrEq, "|="), \
|
TOKEN_KIND(OrEq, "|="), \
|
||||||
TOKEN_KIND(XorEq, "~="), \
|
TOKEN_KIND(XorEq, "~="), \
|
||||||
TOKEN_KIND(AndNotEq, "&~"), \
|
TOKEN_KIND(AndNotEq, "&~="), \
|
||||||
|
TOKEN_KIND(_AssignOpEnd, "_AssignOpEnd"), \
|
||||||
TOKEN_KIND(Increment, "++"), \
|
TOKEN_KIND(Increment, "++"), \
|
||||||
TOKEN_KIND(Decrement, "--"), \
|
TOKEN_KIND(Decrement, "--"), \
|
||||||
TOKEN_KIND(ArrowRight, "->"), \
|
TOKEN_KIND(ArrowRight, "->"), \
|
||||||
TOKEN_KIND(ArrowLeft, "<-"), \
|
TOKEN_KIND(ArrowLeft, "<-"), \
|
||||||
TOKEN_KIND(CmpAnd, "&&"), \
|
TOKEN_KIND(CmpAnd, "&&"), \
|
||||||
TOKEN_KIND(CmpOr, "||"), \
|
TOKEN_KIND(CmpOr, "||"), \
|
||||||
|
TOKEN_KIND(CmpAndEq, "&&="), \
|
||||||
|
TOKEN_KIND(CmpOrEq, "||="), \
|
||||||
\
|
\
|
||||||
TOKEN_KIND(_ComparisonBegin, "_ComparisonBegin"), \
|
TOKEN_KIND(_ComparisonBegin, "_ComparisonBegin"), \
|
||||||
TOKEN_KIND(CmpEq, "=="), \
|
TOKEN_KIND(CmpEq, "=="), \
|
||||||
@@ -77,8 +81,6 @@ TOKEN_KIND(_ComparisonBegin, "_ComparisonBegin"), \
|
|||||||
TOKEN_KIND(GtEq, ">="), \
|
TOKEN_KIND(GtEq, ">="), \
|
||||||
TOKEN_KIND(_ComparisonEnd, "_ComparisonEnd"), \
|
TOKEN_KIND(_ComparisonEnd, "_ComparisonEnd"), \
|
||||||
\
|
\
|
||||||
TOKEN_KIND(CmpAndEq, "&&="), \
|
|
||||||
TOKEN_KIND(CmpOrEq, "||="), \
|
|
||||||
TOKEN_KIND(OpenParen, "("), \
|
TOKEN_KIND(OpenParen, "("), \
|
||||||
TOKEN_KIND(CloseParen, ")"), \
|
TOKEN_KIND(CloseParen, ")"), \
|
||||||
TOKEN_KIND(OpenBracket, "["), \
|
TOKEN_KIND(OpenBracket, "["), \
|
||||||
|
|||||||
Reference in New Issue
Block a user