mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Basic Comparisons
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
int main() {
|
int main() {
|
||||||
float a = 0.5;
|
float a = 0.5;
|
||||||
|
float b = 1.5;
|
||||||
|
int c = a < b;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,5 @@ define void @main() {
|
|||||||
entry:
|
entry:
|
||||||
%0 = alloca i64, align 8 ; a
|
%0 = alloca i64, align 8 ; a
|
||||||
store i64 zeroinitializer, i64* %0
|
store i64 zeroinitializer, i64* %0
|
||||||
%1 = alloca i64, align 8 ; b
|
|
||||||
store i64 zeroinitializer, i64* %1
|
|
||||||
store i64 1, i64* %0
|
|
||||||
store i64 2, i64* %1
|
|
||||||
%2 = load i64, i64* %0
|
|
||||||
%3 = add i64 %2, 1
|
|
||||||
store i64 %3, i64* %0
|
|
||||||
%4 = load i64, i64* %1
|
|
||||||
%5 = add i64 %4, 1
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -1,6 +1,3 @@
|
|||||||
main :: proc() {
|
main :: proc() {
|
||||||
a, b := 1, 2;
|
a : int;
|
||||||
a++;
|
|
||||||
b++;
|
|
||||||
a += b;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,6 @@
|
|||||||
rem del "..\examples\test.bc"
|
rem del "..\examples\test.bc"
|
||||||
call ..\bin\odin.exe ..\examples/test.odin
|
call ..\bin\odin.exe ..\examples/test.odin
|
||||||
call lli ..\examples/test.ll
|
call lli ..\examples/test.ll
|
||||||
rem call clang ..\examples/test.c -S -emit-llvm -o -
|
rem call opt -mem2reg ..\examples/test.ll > ..\examples/test.bc
|
||||||
|
rem call llvm-dis ..\examples/test.bc -o..\examples/test.ll
|
||||||
|
rem call clang ..\examples/test.c -O1 -S -emit-llvm -o ..\examples/test-c.ll
|
||||||
|
|||||||
+53
-23
@@ -278,33 +278,63 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) {
|
|||||||
|
|
||||||
ssa_fprintf(f, "%%%d = ", value->id);
|
ssa_fprintf(f, "%%%d = ", value->id);
|
||||||
|
|
||||||
if (is_type_float(type))
|
if (gb_is_between(bo->op.kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
|
||||||
ssa_fprintf(f, "f");
|
if (is_type_float(type)) {
|
||||||
|
ssa_fprintf(f, "fcmp ");
|
||||||
switch (bo->op.kind) {
|
switch (bo->op.kind) {
|
||||||
case Token_Add: ssa_fprintf(f, "add"); break;
|
case Token_CmpEq: ssa_fprintf(f, "oeq"); break;
|
||||||
case Token_Sub: ssa_fprintf(f, "sub"); break;
|
case Token_NotEq: ssa_fprintf(f, "one"); break;
|
||||||
case Token_And: ssa_fprintf(f, "and"); break;
|
case Token_Lt: ssa_fprintf(f, "olt"); break;
|
||||||
case Token_Or: ssa_fprintf(f, "or"); break;
|
case Token_Gt: ssa_fprintf(f, "ogt"); break;
|
||||||
case Token_Xor: ssa_fprintf(f, "xor"); break;
|
case Token_LtEq: ssa_fprintf(f, "ole"); break;
|
||||||
|
case Token_GtEq: ssa_fprintf(f, "oge"); break;
|
||||||
case Token_AndNot: GB_PANIC("TODO(bill): print Token_AndNot");
|
}
|
||||||
|
} else {
|
||||||
case Token_Mul: ssa_fprintf(f, "mul"); break;
|
ssa_fprintf(f, "icmp ");
|
||||||
|
if (bo->op.kind != Token_CmpEq &&
|
||||||
default: {
|
bo->op.kind != Token_NotEq) {
|
||||||
if (!is_type_float(type)) {
|
if (is_type_unsigned(type)) {
|
||||||
if (is_type_unsigned(type))
|
ssa_fprintf(f, "s");
|
||||||
ssa_fprintf(f, "u");
|
} else {
|
||||||
else
|
ssa_fprintf(f, "u");
|
||||||
ssa_fprintf(f, "s");
|
}
|
||||||
|
}
|
||||||
|
switch (bo->op.kind) {
|
||||||
|
case Token_CmpEq: ssa_fprintf(f, "eq"); break;
|
||||||
|
case Token_NotEq: ssa_fprintf(f, "ne"); break;
|
||||||
|
case Token_Lt: ssa_fprintf(f, "lt"); break;
|
||||||
|
case Token_Gt: ssa_fprintf(f, "gt"); break;
|
||||||
|
case Token_LtEq: ssa_fprintf(f, "le"); break;
|
||||||
|
case Token_GtEq: ssa_fprintf(f, "ge"); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (is_type_float(type))
|
||||||
|
ssa_fprintf(f, "f");
|
||||||
|
|
||||||
switch (bo->op.kind) {
|
switch (bo->op.kind) {
|
||||||
case Token_Quo: ssa_fprintf(f, "div"); break;
|
case Token_Add: ssa_fprintf(f, "add"); break;
|
||||||
case Token_Mod: ssa_fprintf(f, "rem"); break;
|
case Token_Sub: ssa_fprintf(f, "sub"); break;
|
||||||
|
case Token_And: ssa_fprintf(f, "and"); break;
|
||||||
|
case Token_Or: ssa_fprintf(f, "or"); break;
|
||||||
|
case Token_Xor: ssa_fprintf(f, "xor"); break;
|
||||||
|
|
||||||
|
case Token_AndNot: GB_PANIC("Token_AndNot Should never be called");
|
||||||
|
|
||||||
|
case Token_Mul: ssa_fprintf(f, "mul"); break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
if (!is_type_float(type)) {
|
||||||
|
if (is_type_unsigned(type)) ssa_fprintf(f, "u");
|
||||||
|
else ssa_fprintf(f, "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (bo->op.kind) {
|
||||||
|
case Token_Quo: ssa_fprintf(f, "div"); break;
|
||||||
|
case Token_Mod: ssa_fprintf(f, "rem"); break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
|
|||||||
+64
-3
@@ -104,6 +104,7 @@ struct ssaInstruction {
|
|||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
Type *type;
|
||||||
Token op;
|
Token op;
|
||||||
ssaValue *left, *right;
|
ssaValue *left, *right;
|
||||||
} binary_op;
|
} binary_op;
|
||||||
@@ -114,10 +115,10 @@ struct ssaInstruction {
|
|||||||
enum ssaValueKind {
|
enum ssaValueKind {
|
||||||
ssaValue_Invalid,
|
ssaValue_Invalid,
|
||||||
|
|
||||||
|
ssaValue_Constant,
|
||||||
ssaValue_TypeName,
|
ssaValue_TypeName,
|
||||||
ssaValue_Global,
|
ssaValue_Global,
|
||||||
ssaValue_Procedure,
|
ssaValue_Procedure,
|
||||||
ssaValue_Constant,
|
|
||||||
|
|
||||||
ssaValue_Block,
|
ssaValue_Block,
|
||||||
ssaValue_Instruction,
|
ssaValue_Instruction,
|
||||||
@@ -130,10 +131,10 @@ struct ssaValue {
|
|||||||
i32 id;
|
i32 id;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
ssaConstant constant;
|
||||||
ssaTypeName type_name;
|
ssaTypeName type_name;
|
||||||
ssaGlobal global;
|
ssaGlobal global;
|
||||||
ssaProcedure procedure;
|
ssaProcedure procedure;
|
||||||
ssaConstant constant;
|
|
||||||
ssaBlock block;
|
ssaBlock block;
|
||||||
ssaInstruction instruction;
|
ssaInstruction instruction;
|
||||||
};
|
};
|
||||||
@@ -157,6 +158,7 @@ struct ssaLvalue {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void ssa_module_init(ssaModule *m, Checker *c) {
|
void ssa_module_init(ssaModule *m, Checker *c) {
|
||||||
m->allocator = gb_heap_allocator();
|
m->allocator = gb_heap_allocator();
|
||||||
m->info = &c->info;
|
m->info = &c->info;
|
||||||
@@ -187,6 +189,8 @@ Type *ssa_instruction_type(ssaInstruction *instr) {
|
|||||||
return ssa_value_type(instr->store.address);
|
return ssa_value_type(instr->store.address);
|
||||||
case ssaInstruction_Load:
|
case ssaInstruction_Load:
|
||||||
return ssa_value_type(instr->load.address);
|
return ssa_value_type(instr->load.address);
|
||||||
|
case ssaInstruction_BinaryOp:
|
||||||
|
return instr->binary_op.type;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -202,6 +206,9 @@ void ssa_instruction_set_type(ssaInstruction *instr, Type *type) {
|
|||||||
case ssaInstruction_Load:
|
case ssaInstruction_Load:
|
||||||
// NOTE(bill): Do nothing
|
// NOTE(bill): Do nothing
|
||||||
break;
|
break;
|
||||||
|
case ssaInstruction_BinaryOp:
|
||||||
|
instr->binary_op.type = type;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,6 +565,31 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue
|
|||||||
return ssa_emit(proc, v);
|
return ssa_emit(proc, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssaValue *ssa_emit_compare(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *right) {
|
||||||
|
Type *a = get_base_type(ssa_value_type(left));
|
||||||
|
Type *b = get_base_type(ssa_value_type(right));
|
||||||
|
|
||||||
|
if (op.kind == Token_CmpEq &&
|
||||||
|
left->kind == ssaValue_Constant && left->constant.value.kind == ExactValue_Bool) {
|
||||||
|
if (left->constant.value.value_bool) {
|
||||||
|
if (is_type_boolean(b))
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (are_types_identical(a, b)) {
|
||||||
|
// NOTE(bill): No need for a conversion
|
||||||
|
} else if (left->kind == ssaValue_Constant) {
|
||||||
|
left = ssa_emit_conversion(proc, left, ssa_value_type(right));
|
||||||
|
} else if (right->kind == ssaValue_Constant) {
|
||||||
|
right = ssa_emit_conversion(proc, right, ssa_value_type(left));
|
||||||
|
}
|
||||||
|
|
||||||
|
ssaValue *v = ssa_make_instruction_binary_op(proc, op, left, right);
|
||||||
|
ssa_value_set_type(v, &basic_types[Basic_bool]);
|
||||||
|
return ssa_emit(proc, v);
|
||||||
|
}
|
||||||
|
|
||||||
ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) {
|
ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) {
|
||||||
switch (expr->kind) {
|
switch (expr->kind) {
|
||||||
case AstNode_Identifier: {
|
case AstNode_Identifier: {
|
||||||
@@ -573,6 +605,9 @@ ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAnd
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case AstNode_ParenExpression:
|
||||||
|
return ssa_build_single_expression(proc, unparen_expression(expr), tv);
|
||||||
|
|
||||||
case AstNode_DereferenceExpression: {
|
case AstNode_DereferenceExpression: {
|
||||||
ssaLvalue addr = ssa_build_address(proc, expr->dereference_expression.operand);
|
ssaLvalue addr = ssa_build_address(proc, expr->dereference_expression.operand);
|
||||||
return ssa_lvalue_load(addr, proc);
|
return ssa_lvalue_load(addr, proc);
|
||||||
@@ -617,11 +652,37 @@ ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAnd
|
|||||||
case Token_And:
|
case Token_And:
|
||||||
case Token_Or:
|
case Token_Or:
|
||||||
case Token_Xor:
|
case Token_Xor:
|
||||||
case Token_AndNot:
|
|
||||||
return ssa_emit_arith(proc, be->op,
|
return ssa_emit_arith(proc, be->op,
|
||||||
ssa_build_expression(proc, be->left),
|
ssa_build_expression(proc, be->left),
|
||||||
ssa_build_expression(proc, be->right),
|
ssa_build_expression(proc, be->right),
|
||||||
tv->type);
|
tv->type);
|
||||||
|
|
||||||
|
case Token_AndNot: {
|
||||||
|
AstNode ue = {AstNode_UnaryExpression};
|
||||||
|
ue.unary_expression.op = be->op;
|
||||||
|
ue.unary_expression.op.kind = Token_Xor;
|
||||||
|
ue.unary_expression.operand = be->right;
|
||||||
|
ssaValue *left = ssa_build_expression(proc, be->left);
|
||||||
|
ssaValue *right = ssa_build_expression(proc, &ue);
|
||||||
|
Token op = be->op;
|
||||||
|
op.kind = Token_And;
|
||||||
|
return ssa_emit_arith(proc, op, left, right, tv->type);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Token_CmpEq:
|
||||||
|
case Token_NotEq:
|
||||||
|
case Token_Lt:
|
||||||
|
case Token_LtEq:
|
||||||
|
case Token_Gt:
|
||||||
|
case Token_GtEq: {
|
||||||
|
ssaValue *cmp = ssa_emit_compare(proc, be->op,
|
||||||
|
ssa_build_expression(proc, be->left),
|
||||||
|
ssa_build_expression(proc, be->right));
|
||||||
|
return ssa_emit_conversion(proc, cmp, default_type(tv->type));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
GB_PANIC("Invalid binary expression");
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case AstNode_ProcedureLiteral:
|
case AstNode_ProcedureLiteral:
|
||||||
|
|||||||
+1
-1
@@ -74,9 +74,9 @@ TOKEN_KIND(_AssignOpEnd, "_AssignOpEnd"), \
|
|||||||
\
|
\
|
||||||
TOKEN_KIND(_ComparisonBegin, "_ComparisonBegin"), \
|
TOKEN_KIND(_ComparisonBegin, "_ComparisonBegin"), \
|
||||||
TOKEN_KIND(CmpEq, "=="), \
|
TOKEN_KIND(CmpEq, "=="), \
|
||||||
|
TOKEN_KIND(NotEq, "!="), \
|
||||||
TOKEN_KIND(Lt, "<"), \
|
TOKEN_KIND(Lt, "<"), \
|
||||||
TOKEN_KIND(Gt, ">"), \
|
TOKEN_KIND(Gt, ">"), \
|
||||||
TOKEN_KIND(NotEq, "!="), \
|
|
||||||
TOKEN_KIND(LtEq, "<="), \
|
TOKEN_KIND(LtEq, "<="), \
|
||||||
TOKEN_KIND(GtEq, ">="), \
|
TOKEN_KIND(GtEq, ">="), \
|
||||||
TOKEN_KIND(_ComparisonEnd, "_ComparisonEnd"), \
|
TOKEN_KIND(_ComparisonEnd, "_ComparisonEnd"), \
|
||||||
|
|||||||
Reference in New Issue
Block a user