Skip to content

Commit

Permalink
added for loops; fixed binop bug
Browse files Browse the repository at this point in the history
  • Loading branch information
nmosier committed Jan 16, 2020
1 parent 0becc3c commit 528acc9
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 51 deletions.
10 changes: 9 additions & 1 deletion DIARY
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,17 @@ structs on [1], [2], [3] share the same unique ID, while [4] has a different uni
that these operators are working. Interestingly, there is no penalty for pre- vs. post-increment/decrement on chars (single-byte values); however, there _is_ a penalty for post-inc'ing/dec'ing
ints.

[6 hrs] Added typedefs. TODO

[1 hr] Added for loop.

01/15/2020
[1 hr] Wrote tests for loop; fixed binary operation bug (invalid 'case' fallthrough in switch statement, leading to incorrect type being assigned). Added comma operator (the one that separates
expressions).

TODO
[ ] typedef
[X] ++, --
[ ] +=, *=, etc.
[ ] for
[ ] for

1 change: 1 addition & 0 deletions ast/ast-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ namespace zc {
case Kind::BOP_TIMES: return l * r;
case Kind::BOP_DIVIDE: return l / r;
case Kind::BOP_MOD: return l % r;
case Kind::BOP_COMMA: return r;
}
}

Expand Down
7 changes: 3 additions & 4 deletions ast/ast-expr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ namespace zc {
BOP_MINUS,
BOP_TIMES,
BOP_DIVIDE,
BOP_MOD
BOP_MOD,
BOP_COMMA
};
Kind kind() const { return kind_; }
bool is_logical() const;
Expand Down Expand Up @@ -206,9 +207,7 @@ namespace zc {

virtual void TypeCheck(SemantEnv& env) override;

virtual Block *CodeGen(CgenEnv& env, Block *block, ExprKind mode) override {
abort();
}
virtual Block *CodeGen(CgenEnv& env, Block *block, ExprKind mode) override { return block; }

protected:
NoExpr(const SourceLoc& loc): ASTExpr(loc) {}
Expand Down
34 changes: 24 additions & 10 deletions ast/ast-stat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,6 @@ namespace zc {
SelectionStat(args...), cond_(cond), if_body_(if_body), else_body_(else_body) {}
};

#if 0
class SwitchStat: public SelectionStat {
public:

private:
ASTExpr *control_;

};
#endif

/* NOTE: Abstract */
class IterationStat: public ASTStat {
public:
Expand Down Expand Up @@ -226,6 +216,30 @@ namespace zc {
WhileStat(Args... args): IterationStat(args...) {}
};

class ForStat: public IterationStat {
public:
ASTExpr *init() const { return init_; }
ASTExpr *after() const { return after_; }

/* Semantic Analysis */
virtual void TypeCheck(SemantEnv& env) override;

/* Code Generation */
virtual Block *CodeGen(CgenEnv& env, Block *block) override;
virtual void FrameGen(StackFrame& env) const override;

template <typename... Args>
static ForStat *Create(Args... args) { return new ForStat(args...); }

private:
ASTExpr *init_;
ASTExpr *after_;

template <typename... Args>
ForStat(ASTExpr *init, ASTExpr *cond, ASTExpr *after, Args... args):
IterationStat(cond, args...), init_(init), after_(after) {}
};

class GotoStat: public ASTStat {
public:
Identifier *label_id() const { return label_id_; }
Expand Down
1 change: 1 addition & 0 deletions c.l
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ E [Ee][+-]?{D}+
"if" { return IF; }
"else" { return ELSE; }
"while" { return WHILE; }
"for" { return FOR; }

"auto" { return AUTO; }
"register" { return REGISTER; }
Expand Down
9 changes: 8 additions & 1 deletion c.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
%token IF
%token ELSE
%token WHILE
%token FOR

/* STORAGE CLASS SPECS */
%token AUTO REGISTER STATIC EXTERN TYPEDEF
Expand Down Expand Up @@ -378,14 +379,18 @@ iteration_stat:
WHILE '(' exp ')' stat {
$$ = zc::WhileStat::Create($3, $5, @3);
}
| FOR '(' optional_exp ';' optional_exp ';' optional_exp ')' stat {
$$ = zc::ForStat::Create($3, $5, $7, $9, @1);
}
;
exp_stat: optional_exp ';' { $$ = zc::ExprStat::Create($1, @1); }
;
optional_exp: /* empty */ { $$ = zc::NoExpr::Create(@$); @$ = 0; }
| exp { $$ = $1; }
;
exp: assignment_exp { $$ = $1; }
; /* incomplete */
| exp ',' assignment_exp { $$ = zc::BinaryExpr::Create(zc::BinaryExpr::Kind::BOP_COMMA, $1, $3, @1); }
;
assignment_exp: conditional_exp { $$ = $1; }
| unary_exp '=' conditional_exp { $$ = zc::AssignmentExpr::Create($1, $3, @1); }
; /* incomplete */
Expand Down Expand Up @@ -537,6 +542,8 @@ equality_operator:
relational_operator:
'<' { $$ = zc::BinaryExpr::Kind::BOP_LT; }
| LEQ { $$ = zc::BinaryExpr::Kind::BOP_LEQ; }
| '>' { $$ = zc::BinaryExpr::Kind::BOP_GT; }
| GEQ { $$ = zc::BinaryExpr::Kind::BOP_GEQ; }
; /* incomplete */
additive_operator:
'+' { $$ = zc::BinaryExpr::Kind::BOP_PLUS; }
Expand Down
91 changes: 57 additions & 34 deletions cgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,30 +158,6 @@ namespace zc {

return block;
}

#if 0
void ASTType::CodeGen(CgenEnv& env) {
SymInfo *info = env.ext_env().frame().next_local(this);

if (sym() != nullptr) {
/* if this type is bounded to a symbol, declare that symbol */
env.symtab().AddToScope(sym(), info);
}
}
#endif

#if 0
void EnumType::CodeGen(CgenEnv& env) {
for (auto memb : *membs()) {
const auto imm = new ImmediateValue(memb->eval(), bytes());
auto info = new ConstSymInfo(this, imm);
env.symtab().AddToScope(memb->sym(), info);
}

ASTType::CodeGen(env);
}
#endif

Block *ReturnStat::CodeGen(CgenEnv& env, Block *block) {
/* generate returned expression
* For now, assume result will be in %a or %hl. */
Expand Down Expand Up @@ -258,7 +234,7 @@ namespace zc {
env.stat_stack().Push(stat_info);

pred_block = pred()->CodeGen(env, pred_block, ASTExpr::ExprKind::EXPR_RVALUE);
emit_nonzero_test(env, block, pred()->type()->bytes());
emit_nonzero_test(env, pred_block, pred()->type()->bytes()); /* CHANGED */
pred_block->transitions().vec().push_back(new JumpTransition(body_block, Cond::NZ));
pred_block->transitions().vec().push_back(new JumpTransition(join_block, Cond::ANY));

Expand All @@ -272,6 +248,42 @@ namespace zc {
return join_block;
}

Block *ForStat::CodeGen(CgenEnv& env, Block *block) {
Label *cond_label = new_label("for_cond");
Block *cond_block = new Block(cond_label);
BlockTransition *cond_trans = new JumpTransition(cond_block, Cond::ANY);

Label *after_label = new_label("for_after");
Block *after_block = new Block(after_label);
BlockTransition *after_trans = new JumpTransition(after_block, Cond::ANY);

Label *body_label = new_label("for_body");
Block *body_block = new Block(body_label);
BlockTransition *body_trans = new JumpTransition(body_block, Cond::NZ);

Label *join_label = new_label("for_join");
Block *join_block = new Block(join_label);
BlockTransition *join_trans = new JumpTransition(join_block, Cond::ANY);

StatInfo *stat_info = new StatInfo(this, after_block, join_block);
env.stat_stack().Push(stat_info);

block = init()->CodeGen(env, block, ASTExpr::ExprKind::EXPR_RVALUE);
block->transitions().vec().push_back(cond_trans);
block = pred()->CodeGen(env, cond_block, ASTExpr::ExprKind::EXPR_RVALUE);
emit_nonzero_test(env, block, pred()->type()->bytes());
block->transitions().vec().push_back(body_trans);
block->transitions().vec().push_back(join_trans);
block = body()->CodeGen(env, body_block);
block->transitions().vec().push_back(after_trans);
block = after()->CodeGen(env, after_block, ASTExpr::ExprKind::EXPR_RVALUE);
block->transitions().vec().push_back(cond_trans);

env.stat_stack().Pop();

return join_block;
}

Block *BreakStat::CodeGen(CgenEnv& env, Block *block) {
StatInfo *stat_info = env.stat_stack().Find([](auto info){return info->stat()->can_break(); });
block->transitions().vec().push_back(new JumpTransition(stat_info->exit(), Cond::ANY));
Expand Down Expand Up @@ -600,7 +612,7 @@ namespace zc {

case Kind::BOP_EQ:
case Kind::BOP_NEQ:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (lhs()->type()->bytes()) {
case byte_size:
block->instrs().push_back(new CompInstruction(&rv_a, &rv_b));
Expand All @@ -617,7 +629,7 @@ namespace zc {
break;

case Kind::BOP_LT:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (lhs()->type()->bytes()) {
case byte_size:
/* cp a,b
Expand All @@ -644,7 +656,7 @@ namespace zc {
break;

case Kind::BOP_LEQ:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (lhs()->type()->bytes()) {
case byte_size:
/* scf
Expand Down Expand Up @@ -674,7 +686,7 @@ namespace zc {
break;

case Kind::BOP_GT:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (lhs()->type()->bytes()) {
case byte_size:
/* dec a
Expand Down Expand Up @@ -706,7 +718,7 @@ namespace zc {
break;

case Kind::BOP_GEQ:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (lhs()->type()->bytes()) {
case byte_size:
/* cp a,b
Expand Down Expand Up @@ -734,7 +746,7 @@ namespace zc {
break;

case Kind::BOP_PLUS:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (type()->bytes()) {
case byte_size:
/* add a,b */
Expand All @@ -749,7 +761,7 @@ namespace zc {
break;

case Kind::BOP_MINUS:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (type()->bytes()) {
case byte_size:
/* sub a,b */
Expand All @@ -767,7 +779,7 @@ namespace zc {
break;

case Kind::BOP_TIMES:
emit_binop(env, block, this);
block = emit_binop(env, block, this);
switch (type()->bytes()) {
case byte_size:
/* ld c,a
Expand All @@ -791,6 +803,11 @@ namespace zc {
case Kind::BOP_BITWISE_XOR:
/* TODO */
abort();

case Kind::BOP_COMMA:
lhs()->CodeGen(env, block, ExprKind::EXPR_RVALUE);
rhs()->CodeGen(env, block, mode);
break;
}

return block;
Expand Down Expand Up @@ -1101,7 +1118,7 @@ namespace zc {
}
}

void emit_binop(CgenEnv& env, Block *block, ASTBinaryExpr *expr) {
Block *emit_binop(CgenEnv& env, Block *block, ASTBinaryExpr *expr) {
Block::InstrVec& instrs = block->instrs();
int bytes = expr->type()->bytes();
int lhs_bytes = expr->lhs()->type()->bytes();
Expand Down Expand Up @@ -1137,6 +1154,8 @@ namespace zc {
break;
default: abort();
}

return block;
}

void emit_crt(const std::string& name, Block *block) {
Expand Down Expand Up @@ -1407,6 +1426,10 @@ namespace zc {
body()->FrameGen(frame);
}

void ForStat::FrameGen(StackFrame& frame) const {
body()->FrameGen(frame);
}

void VarDeclaration::FrameGen(StackFrame& frame) const {
frame.add_local(this);
}
Expand Down
2 changes: 1 addition & 1 deletion cgen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ namespace zc {
* Generic emission routine for performing binary operation on two integers.
* Post condition: lhs in %a or %hl; hs in %b or %de, depending on size.
*/
void emit_binop(CgenEnv& env, Block *block, ASTBinaryExpr *expr);
Block *emit_binop(CgenEnv& env, Block *block, ASTBinaryExpr *expr);

/**
* Emit instructions that move the contents of the zero flag (ZF) into register %a.
Expand Down
17 changes: 17 additions & 0 deletions semant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,15 @@
env.stat_stack().Pop();
}

void ForStat::TypeCheck(SemantEnv& env) {
env.stat_stack().Push(this);
init()->TypeCheck(env);
pred()->TypeCheck(env);
after()->TypeCheck(env);
body()->TypeCheck(env);
env.stat_stack().Pop();
}

void GotoStat::TypeCheck(SemantEnv& env) {
env.ext_env().LabelRef(label_id());
}
Expand Down Expand Up @@ -700,6 +709,11 @@
type_ = IntegralType::Create(IntegralType::IntKind::SPEC_CHAR, loc());
}
}
break;

case Kind::BOP_COMMA:
type_ = rhs()->type();
break;
}
}

Expand Down Expand Up @@ -785,6 +799,9 @@
case Kind::BOP_DIVIDE:
case Kind::BOP_MOD:
return ExprKind::EXPR_RVALUE;

case Kind::BOP_COMMA:
return ExprKind::EXPR_LVALUE;
}
}

Expand Down
9 changes: 9 additions & 0 deletions tst/semant/for-break.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
int main(int argc, char **argv) {
for (; argc > 0; --argc) {
if (argc == 1) {
break;
}
}

return argc;
}
Loading

0 comments on commit 528acc9

Please sign in to comment.