aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorgingerBill <ginger.bill.22@gmail.com>2016-08-01 00:34:15 +0100
committergingerBill <ginger.bill.22@gmail.com>2016-08-01 00:34:15 +0100
commit88e05ad2b25b51ad3f5dd92554ffbfa3eeaa57b9 (patch)
treef4aa339987a8aa05a86bfa410503200dfa7d72b7 /src/codegen
parent70f6282f41cdd7f500159116c520140364f6739a (diff)
Basic Comparisons
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/print.cpp76
-rw-r--r--src/codegen/ssa.cpp67
2 files changed, 117 insertions, 26 deletions
diff --git a/src/codegen/print.cpp b/src/codegen/print.cpp
index 8e7f33ac9..63b846c46 100644
--- a/src/codegen/print.cpp
+++ b/src/codegen/print.cpp
@@ -278,33 +278,63 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) {
ssa_fprintf(f, "%%%d = ", value->id);
- if (is_type_float(type))
- ssa_fprintf(f, "f");
-
- switch (bo->op.kind) {
- case Token_Add: ssa_fprintf(f, "add"); 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("TODO(bill): print Token_AndNot");
-
- 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");
+ if (gb_is_between(bo->op.kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
+ if (is_type_float(type)) {
+ ssa_fprintf(f, "fcmp ");
+ switch (bo->op.kind) {
+ case Token_CmpEq: ssa_fprintf(f, "oeq"); break;
+ case Token_NotEq: ssa_fprintf(f, "one"); break;
+ case Token_Lt: ssa_fprintf(f, "olt"); break;
+ case Token_Gt: ssa_fprintf(f, "ogt"); break;
+ case Token_LtEq: ssa_fprintf(f, "ole"); break;
+ case Token_GtEq: ssa_fprintf(f, "oge"); break;
+ }
+ } else {
+ ssa_fprintf(f, "icmp ");
+ if (bo->op.kind != Token_CmpEq &&
+ bo->op.kind != Token_NotEq) {
+ if (is_type_unsigned(type)) {
+ ssa_fprintf(f, "s");
+ } else {
+ ssa_fprintf(f, "u");
+ }
+ }
+ 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) {
- case Token_Quo: ssa_fprintf(f, "div"); break;
- case Token_Mod: ssa_fprintf(f, "rem"); break;
+ case Token_Add: ssa_fprintf(f, "add"); 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, " ");
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index 070c3a1d6..b7d925d07 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -104,6 +104,7 @@ struct ssaInstruction {
struct {
+ Type *type;
Token op;
ssaValue *left, *right;
} binary_op;
@@ -114,10 +115,10 @@ struct ssaInstruction {
enum ssaValueKind {
ssaValue_Invalid,
+ ssaValue_Constant,
ssaValue_TypeName,
ssaValue_Global,
ssaValue_Procedure,
- ssaValue_Constant,
ssaValue_Block,
ssaValue_Instruction,
@@ -130,10 +131,10 @@ struct ssaValue {
i32 id;
union {
+ ssaConstant constant;
ssaTypeName type_name;
ssaGlobal global;
ssaProcedure procedure;
- ssaConstant constant;
ssaBlock block;
ssaInstruction instruction;
};
@@ -157,6 +158,7 @@ struct ssaLvalue {
};
};
+
void ssa_module_init(ssaModule *m, Checker *c) {
m->allocator = gb_heap_allocator();
m->info = &c->info;
@@ -187,6 +189,8 @@ Type *ssa_instruction_type(ssaInstruction *instr) {
return ssa_value_type(instr->store.address);
case ssaInstruction_Load:
return ssa_value_type(instr->load.address);
+ case ssaInstruction_BinaryOp:
+ return instr->binary_op.type;
}
return NULL;
}
@@ -202,6 +206,9 @@ void ssa_instruction_set_type(ssaInstruction *instr, Type *type) {
case ssaInstruction_Load:
// NOTE(bill): Do nothing
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);
}
+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) {
switch (expr->kind) {
case AstNode_Identifier: {
@@ -573,6 +605,9 @@ ssaValue *ssa_build_single_expression(ssaProcedure *proc, AstNode *expr, TypeAnd
}
} break;
+ case AstNode_ParenExpression:
+ return ssa_build_single_expression(proc, unparen_expression(expr), tv);
+
case AstNode_DereferenceExpression: {
ssaLvalue addr = ssa_build_address(proc, expr->dereference_expression.operand);
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_Or:
case Token_Xor:
- case Token_AndNot:
return ssa_emit_arith(proc, be->op,
ssa_build_expression(proc, be->left),
ssa_build_expression(proc, be->right),
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;
case AstNode_ProcedureLiteral: