Skip to content

Commit

Permalink
Generate correct arithmetic instructions based on operand sign
Browse files Browse the repository at this point in the history
  • Loading branch information
kukrimate committed Oct 18, 2022
1 parent 2657138 commit ee15113
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 13 deletions.
3 changes: 3 additions & 0 deletions cc3.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ enum {
| TY_SHORT | TY_USHORT | TY_INT | TY_UINT
| TY_LONG | TY_ULONG | TY_LLONG | TY_ULLONG,

// Signed integer types
TY_SIG_MASK = TY_CHAR | TY_SCHAR | TY_SHORT | TY_INT | TY_LONG | TY_LLONG,

// Arithmetic type
TY_ARITH_MASK = TY_INT_MASK | TY_FLOAT | TY_DOUBLE | TY_LDOUBLE,

Expand Down
58 changes: 46 additions & 12 deletions gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,8 +479,18 @@ void gen_value(gen_t *self, expr_t *expr)
emit_pop(self, "%rcx");

switch (expr->kind) {
case EXPR_DIV: emit(self, "\txorl\t%%edx, %%edx\n\tdivq\t%%rcx\n"); break;
case EXPR_MOD: emit(self, "\txorl\t%%edx, %%edx\n\tdivq\t%%rcx\n\tmovq\t%%rdx, %%rax\n"); break;
case EXPR_DIV:
case EXPR_MOD:
emit(self, "\txorl\t%%edx, %%edx\n");
if (expr->ty->kind & TY_SIG_MASK) {
emit(self, "\tidivq\t%%rcx\n");
} else {
emit(self, "\tdivq\t%%rcx\n");
}
if (expr->kind == EXPR_MOD) {
emit(self, "\tmovq\t%%rdx, %%rax\n");
}
break;
case EXPR_MUL: emit(self, "\timulq\t%%rcx, %%rax\n"); break;
case EXPR_ADD: emit(self, "\taddq\t%%rcx, %%rax\n"); break;
case EXPR_SUB: emit(self, "\tsubq\t%%rcx, %%rax\n"); break;
Expand Down Expand Up @@ -611,17 +621,35 @@ void gen_value(gen_t *self, expr_t *expr)
}
}

static inline const char *jcc(int kind, bool val)
static inline const char *jcc(int kind, bool val, ty_t *ty)
{
// FIXME: signedness
switch (kind) {
case EXPR_LT: return val ? "jl" : "jge";
case EXPR_GT: return val ? "jg" : "jle";
case EXPR_LE: return val ? "jle" : "jg";
case EXPR_GE: return val ? "jge" : "jl";
case EXPR_EQ: return val ? "je" : "jne";
case EXPR_NE: return val ? "jne" : "je";
default: ASSERT_NOT_REACHED();
case EXPR_LT:
if (ty->kind & TY_SIG_MASK)
return val ? "jl" : "jge";
else
return val ? "jb" : "jae";
case EXPR_GT:
if (ty->kind & TY_SIG_MASK)
return val ? "jg" : "jle";
else
return val ? "ja" : "jbe";
case EXPR_LE:
if (ty->kind & TY_SIG_MASK)
return val ? "jle" : "jg";
else
return val ? "jbe" : "ja";
case EXPR_GE:
if (ty->kind & TY_SIG_MASK)
return val ? "jge" : "jl";
else
return val ? "jae" : "jb";
case EXPR_EQ:
return val ? "je" : "jne";
case EXPR_NE:
return val ? "jne" : "je";
default:
ASSERT_NOT_REACHED();
}
}

Expand All @@ -643,7 +671,7 @@ void gen_bool(gen_t *self, expr_t *expr, bool val, int label)
emit_pop(self, "%rax");
emit(self, "\tcmpq\t%%rcx, %%rax\n");
// Generate jump
emit_jump(self, jcc(expr->kind, val), label);
emit_jump(self, jcc(expr->kind, val, expr->as_binary.lhs->ty), label);
break;
case EXPR_LNOT:
gen_bool(self, expr->as_unary.arg, !val, label);
Expand Down Expand Up @@ -989,6 +1017,9 @@ void gen_func(gen_t *self, sym_t *sym, stmt_vec_t *stmts)
if (sym->kind != SYM_STATIC)
emit(self, "\t.globl\t%s\n", sym->asm_name);

// Mark symbol as function (valgrind)
emit(self, "\t.type\t%s,@function\n", sym->asm_name);

// Generate entry sequence
emit(self,
"%s:\n"
Expand Down Expand Up @@ -1059,6 +1090,9 @@ void gen_func(gen_t *self, sym_t *sym, stmt_vec_t *stmts)
"\tleave\n"
"\tret\n");

// Mark length of function (valgrind)
emit(self, "\t.size\t%s,.-%s\n", sym->asm_name, sym->asm_name);

// Provide stackframe size
emit(self, "\t.set\t%s_fs, %d\n", sym->asm_name, ALIGNED(self->offset, 16));
}
Expand Down
2 changes: 1 addition & 1 deletion sema.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@ static void bind_scalar(init_t *out, init_context_t *ctx, ty_t *ty)
// If we reach a member of an aggregate without an initializer, we need to
// zero initialize it. We make that explicit to simplify code generation.
if (ctx->it == ctx->end) {
out->as_expr = convert_by_assignment(ty, make_const_expr(self, &ty_int, 0));
out->as_expr = convert_by_assignment(ty, make_const_expr(&ty_int, 0));
return;
}

Expand Down

0 comments on commit ee15113

Please sign in to comment.