OpenCores
URL https://opencores.org/ocsvn/c16/c16/trunk

Subversion Repositories c16

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /c16/tags/V10/compiler
    from Rev 3 to Rev 26
    Reverse comparison

Rev 3 → Rev 26

/cc80.cc
0,0 → 1,100
 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "List.hh"
#include "Backend.hh"
 
extern FILE * yyin;
extern FILE * out;
extern int yyparse();
 
static int usage(const char * prog, int ret);
 
FILE * out = 0;
 
extern bool is_loader;
extern int memtop;
 
bool is_loader = false;
int memtop = 0;
 
//-----------------------------------------------------------------------------
int main(int argc, char * argv[])
{
int ret = 0;
 
const char * prog = *argv;
argv++;
argc--;
 
if (argc < 1) return usage(prog, 1);
 
if (!strcmp(*argv, "-l"))
{
argv++;
argc--;
is_loader = true;
}
 
if (argc < 1) return usage(prog, 2);
 
memtop = strtol(*argv, 0, 0);
if (!memtop) return usage(prog, 3);
fprintf(stderr, "Top of memory is 0x%X\n", memtop);
argv++;
argc--;
 
if (argc < 1) return usage(prog, 4);
yyin = fopen(*argv, "r");
if (yyin == 0)
{
fprintf(stderr, "Can't open input file %s\n", *argv);
return 5;
}
argv++;
argc--;
 
out = stdout;
if (argc)
{
out = fopen(*argv, "w");
if (out == 0)
{
fprintf(stderr, "Can't open output file %s\n", *argv);
return 6;
}
}
 
Backend::file_header();
 
if (yyparse())
{
fprintf(stderr, "PARSE ERROR\n");
ret = 7;
}
else
{
fprintf(stderr, "PARSED OK\n");
if (Node::GetSemanticErrors())
{
fprintf(stderr, "BUT: %d errors\n", Node::GetSemanticErrors());
ret = Node::GetSemanticErrors();
}
}
 
Backend::file_footer();
 
fclose(yyin);
fclose(out);
yyin = 0;
return ret;
}
//-----------------------------------------------------------------------------
int usage(const char * prog, int ret)
{
fprintf(stderr, "\n%s: Error %d\n", prog, ret);
fprintf(stderr, "\nUsage:\n %s [-l] memtop file.c [file.asm]\n", prog);
return ret;
}
//-----------------------------------------------------------------------------
/Expression.cc
0,0 → 1,1641
// Expression.cc
 
#include <stdio.h>
#include <assert.h>
#include "Node.hh"
#include "Name.hh"
#include "Backend.hh"
 
//-----------------------------------------------------------------------------
Expression * NumericExpression::OptNegate()
{
int_value->Negate();
return this;
}
//-----------------------------------------------------------------------------
Expression * NumericExpression::OptComplement()
{
int_value->Complement();
return this;
}
//-----------------------------------------------------------------------------
Expression * NumericExpression::OptLogNot()
{
int_value->LogNot();
return this;
}
//-----------------------------------------------------------------------------
TypeName * NumericExpression::SetType()
{
assert(int_value);
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
void NumericExpression::EmitInitialization(FILE * out, int size)
{
const int value = int_value->GetValue();
assert(int_value);
if (size == 1) fprintf(out, "\t.BYTE\t%d\n", value);
else if (size == 2) fprintf(out, "\t.WORD\t%d\n", value);
else assert(0 && "Bad size");
}
//-----------------------------------------------------------------------------
NumericExpression::NumericExpression(TypeName * t)
: Expression("NumericExpression (sizeof type)")
{
assert(t);
int_value = new NumericConstant(t->GetSize());
}
//-----------------------------------------------------------------------------
NumericExpression::NumericExpression(Expression * r)
: Expression("NumericExpression (sizeof expr)"),
int_value(0)
{
assert(r);
 
int_value = new NumericConstant(r->GetSize());
}
//-----------------------------------------------------------------------------
const char * NumericExpression::GetPretty(int val)
{
char * cp = new char[50];
assert(cp);
sprintf(cp, "NumericExpression (constant %d = 0x%X)", val, val);
return cp;
 
}
//-----------------------------------------------------------------------------
NumericExpression::NumericExpression(NumericConstant * n)
: Expression(GetPretty(n->GetValue())),
int_value(n)
{
assert(n);
}
//-----------------------------------------------------------------------------
NumericExpression::NumericExpression(int value)
: Expression(GetPretty(value)),
int_value(0)
{
int_value = new NumericConstant(value);
}
//-----------------------------------------------------------------------------
StringExpression::StringExpression(StringConstant * s)
: Expression("StringExpression"),
string_constant(s)
{
}
//-----------------------------------------------------------------------------
TypeName * StringExpression::SetType()
{
/*
TypeSpecifier * con = new TypeSpecifier(TQ_CONST);
Ptr * ptr = new Ptr(con);
Pointer * pointer = new Pointer(ptr, 0);
DeclItem * di = new DeclItem(pointer);
Declarator * decl = new Declarator(di, 0);
TypeSpecifier * ts = new TypeSpecifier(TS_CHAR);
*/
 
char * name = new char[10];
assert(string_constant);
sprintf(name, "Cstr_%d", string_constant->GetStringNumber());
 
const int len = string_constant->GetLength() + 1; // 1 for terminatin 0
Expression * lex = new NumericExpression(len);
 
TypeSpecifier * ts = new TypeSpecifier(TS_CHAR);
 
DeclItem * na_it = new DeclItem(name);
DeclItem * ar_it = new DeclItem(lex);
 
Declarator * ar_dcl = new Declarator(ar_it, 0);
Declarator * na_dcl = new Declarator(na_it, ar_dcl);
return new TypeName(ts, na_dcl);
}
//-----------------------------------------------------------------------------
void StringExpression::EmitInitialization(FILE * out, int size)
{
assert(string_constant);
assert(size == 2);
fprintf(out, "\t.WORD\tCstr_%d\n", string_constant->GetStringNumber());
}
//-----------------------------------------------------------------------------
TypeName * IdentifierExpression::SetType()
{
assert(varname);
TypeName * ret = Name::FindType(varname);
 
if (ret) return ret;
 
fprintf(stderr, "Symbol '%s' not declared\n", varname);
semantic_errors++;
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
MemberExpression::MemberExpression(bool is_pointer, Expression * l,
const char * s)
: Expression("Expression l.member"),
membername(s),
left(l)
{
if (is_pointer) // map l->s to (*l).s
{
left = UnaryExpression::New(ET_CONTENT, left);
}
}
//-----------------------------------------------------------------------------
TypeName * MemberExpression::SetType()
{
assert(left);
return left->GetType()->GetMemberType(membername);
}
//-----------------------------------------------------------------------------
void MemberExpression::Emit(FILE * out)
{
EmitAddress(out, true);
}
//-----------------------------------------------------------------------------
void MemberExpression::EmitAddress(FILE * out)
{
EmitAddress(out, false);
}
//-----------------------------------------------------------------------------
void MemberExpression::EmitAddress(FILE * out, bool content)
{
assert(membername);
 
TypeName * struct_type = left->GetType();
assert(struct_type);
 
if (!struct_type->IsStruct())
{
fprintf(stderr, "request for member %s of non-struct\n", membername);
semantic_errors++;
}
 
TypeSpecifier * ts = struct_type->GetTypeSpecifier();
assert(ts);
 
const char * sname = ts->GetName();
if (sname == 0)
{
fprintf(stderr, "No struct name in member expression\n");
semantic_errors++;
return;
}
 
StructDeclarationList * sdl = StructName::Find(sname);
if (sdl == 0)
{
fprintf(stderr, "No struct %s defined\n", sname);
semantic_errors++;
return;
}
 
int position = -1;
TypeName * membtype = 0;
 
for (; sdl; sdl = sdl->Tail())
{
StructDeclaration * sd = sdl->Head();
assert(sd);
position = sd->GetMemberPosition(sname, membername, ts->IsUnion());
if (position == -1) continue;
 
membtype = sd->GetMemberType(sname, membername);
assert(membtype);
break;
}
 
if (!membtype)
{
fprintf(stderr, "struct %s has no member %s\n", sname, membername);
semantic_errors++;
return;
}
 
left->EmitAddress(out);
Backend::compute_binary(ET_ADD, true, position, "+ (member)");
if (content) Backend::content(membtype->GetSUW());
}
//-----------------------------------------------------------------------------
Expression * UnaryExpression::New(UnaExprType et, Expression * r)
{
assert(r);
 
if (r->IsConstant())
{
switch(et)
{
case ET_CONJUGATE: return r;
case ET_NEGATE: return r->OptNegate();
case ET_COMPLEMENT: return r->OptComplement();
case ET_LOG_NOT: return r->OptLogNot();
}
}
 
switch(et)
{
case ET_POSTINC: // x++ = ++x - 1
{
Expression * pre = UnaryExpression::New(ET_PREINC, r);
NumericConstant * num = new NumericConstant(1);
NumericExpression * one = new NumericExpression(num);
return SubtractionExpression::New(pre, one);
}
 
case ET_POSTDEC: // x-- = --x + 1
{
Expression * pre = UnaryExpression::New(ET_PREDEC, r);
NumericConstant * num = new NumericConstant(1);
NumericExpression * one = new NumericExpression(num);
return AdditionExpression::New(pre, one);
}
}
 
return new UnaryExpression(et, r);
}
//-----------------------------------------------------------------------------
TypeName * UnaryExpression::SetType()
{
assert(right);
switch(expr_type)
{
case ET_CONJUGATE:
case ET_NEGATE:
case ET_COMPLEMENT:
case ET_PREINC:
case ET_PREDEC:
case ET_POSTINC:
case ET_POSTDEC:
return right->GetType();
 
case ET_LOG_NOT:
return new TypeName(TS_INT);
 
case ET_ADDRESS:
return right->GetType()->AddressOf();
 
case ET_CONTENT:
return right->GetType()->ContentOf();
 
default: assert(0 && "Bad unary operator");
}
}
//-----------------------------------------------------------------------------
UnaryExpression::UnaryExpression(TypeName * t, Expression * r)
: Expression("Expression (cast)r"),
expr_type(ET_CAST),
right(r)
{
assert(right);
Expression::SetType(t);
}
//-----------------------------------------------------------------------------
Expression * AdditionExpression::New(Expression * l, Expression * r)
{
if (l->IsVariable() && l->IsArray())
{
l = UnaryExpression::New(ET_ADDRESS, l);
}
 
if (r->IsVariable() && r->IsArray())
{
r = UnaryExpression::New(ET_ADDRESS, r);
}
 
if (l->IsNumericConstant() && r->IsNumericConstant())
{
const int lval = l->GetConstantNumericValue();
const int rval = r->GetConstantNumericValue();
delete l;
delete r;
return new NumericExpression(lval + rval);
}
 
return new AdditionExpression(l, r);
}
//-----------------------------------------------------------------------------
Expression * SubtractionExpression::New(Expression * l, Expression * r)
{
if (l->IsNumericConstant() && r->IsNumericConstant())
{
const int lval = l->GetConstantNumericValue();
const int rval = r->GetConstantNumericValue();
delete l;
delete r;
return new NumericExpression(lval - rval);
}
 
return new SubtractionExpression(l, r);
}
//-----------------------------------------------------------------------------
Expression * BinaryExpression::New(BinExprType et, Expression * l,
Expression * r)
{
assert(l);
if (!r) return new BinaryExpression(et, l, r); // function call
 
if (l->IsNumericConstant() && r->IsNumericConstant())
{
const int lval = l->GetConstantNumericValue();
const int rval = r->GetConstantNumericValue();
switch(et)
{
case ET_LIST:
delete l;
return r;
 
case ET_BIT_OR:
delete l;
delete r;
return new NumericExpression(lval | rval);
 
case ET_BIT_AND:
delete l;
delete r;
return new NumericExpression(lval & rval);
 
case ET_BIT_XOR:
delete l;
delete r;
return new NumericExpression(lval ^ rval);
 
case ET_LOG_OR:
delete l;
delete r;
if (lval || rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_LOG_AND:
delete l;
delete r;
if (lval || rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_EQUAL:
delete l;
delete r;
if (lval == rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_NOT_EQUAL:
delete l;
delete r;
if (lval != rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_LESS_EQUAL:
delete l;
delete r;
if (lval <= rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_LESS:
delete l;
delete r;
if (lval < rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_GREATER_EQUAL:
delete l;
delete r;
if (lval >= rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_GREATER:
delete l;
delete r;
if (lval > rval) return new NumericExpression(-1);
return new NumericExpression(0);
 
case ET_LEFT:
delete l;
delete r;
return new NumericExpression(lval << rval);
 
case ET_RIGHT:
delete l;
delete r;
return new NumericExpression(lval >> rval);
 
case ET_MULT:
delete l;
delete r;
return new NumericExpression(lval * rval);
 
case ET_DIV:
delete l;
delete r;
assert(rval);
return new NumericExpression(lval / rval);
 
case ET_MOD:
delete l;
delete r;
assert(rval);
return new NumericExpression(lval % rval);
}
}
 
if (l->IsNumericConstant())
{
const int lval = l->GetConstantNumericValue();
switch(et)
{
case ET_LIST:
delete l;
return r;
 
case ET_LOG_OR:
delete l;
if (lval == 0) return r;
delete r;
return new NumericExpression(-1);
 
case ET_LOG_AND:
delete l;
if (lval != 0) return r;
delete r;
return new NumericExpression(0);
}
}
else if (l->IsConstant()) // otherwise string (pointer) : always nonzero
{
assert(l->IsStringConstant());
switch(et)
{
case ET_LOG_OR:
delete l;
delete r;
return new NumericExpression(-1);
 
case ET_LOG_AND:
delete l;
return r;
 
case ET_LIST:
delete l;
return r;
}
}
 
if (r->IsNumericConstant())
{
const int rval = r->GetConstantNumericValue();
switch(et)
{
case ET_LOG_OR:
if (!rval) return l;
break;
 
case ET_LOG_AND:
if (rval) return l;
break;
 
}
}
else if (r->IsConstant()) // otherwise string (pointer) : always nonzero
{
assert(r->IsStringConstant());
switch(et)
{
case ET_LOG_AND: return r;
}
}
 
return new BinaryExpression(et, l, r);
}
//-----------------------------------------------------------------------------
BinaryExpression::BinaryExpression(BinExprType et,
Expression * l, Expression * r)
: Expression(GetPrettyName(GetPretty(et))),
expr_type(et),
left(l),
right(r)
{
switch(expr_type)
{
case ET_ADD_ASSIGN: // expr += expr
right = AdditionExpression::New(l, right);
expr_type = ET_ASSIGN;
return;
 
case ET_SUB_ASSIGN: // expr -= expr
right = SubtractionExpression::New(l, right);
expr_type = ET_ASSIGN;
return;
 
case ET_MULT_ASSIGN: // expr *= expr
case ET_DIV_ASSIGN: // expr /= expr
case ET_MOD_ASSIGN: // expr %= expr
case ET_LEFT_ASSIGN: // expr <<= expr
case ET_RIGHT_ASSIGN: // expr >>= expr
case ET_AND_ASSIGN: // expr &= expr
case ET_XOR_ASSIGN: // expr ^= expr
case ET_OR_ASSIGN: // expr |= expr
right = new BinaryExpression(MapAssign(expr_type), l, right);
expr_type = ET_ASSIGN;
return;
}
}
//-----------------------------------------------------------------------------
TypeName * BinaryExpression::SetType()
{
assert(left);
assert(right || expr_type == ET_FUNCALL); // zero if no args
 
switch(expr_type)
{
case ET_LIST: // expr , expr
case ET_LEFT: // expr << expr
case ET_RIGHT: // expr >> expr
return right->GetType();
 
case ET_ASSIGN: // expr = expr
return left->GetType();
 
case ET_EQUAL: // expr == expr
case ET_NOT_EQUAL: // expr != expr
case ET_LESS_EQUAL: // expr <= expr
case ET_LESS: // expr < expr
case ET_GREATER_EQUAL: // expr >= expr
case ET_GREATER: // expr > expr
case ET_BIT_OR: // expr | expr
case ET_BIT_AND: // expr & expr
case ET_BIT_XOR: // expr ^ expr
case ET_MULT: // expr * expr
case ET_DIV: // expr / expr
case ET_MOD: // expr % expr
return MaxType(left, right);
 
case ET_LOG_OR: // expr || expr
case ET_LOG_AND: // expr && expr
return new TypeName(TS_INT);
 
case ET_FUNCALL: // expr ( ... )
return left->FunReturnType();
 
case ET_ELEMENT: // expr [ expr ]
return left->GetType()->ContentOf();
}
assert(0 && "Bad binary operator");
}
//-----------------------------------------------------------------------------
TypeName * AdditionExpression::SetType()
{
assert(left);
assert(right);
 
if (left->GetType()->IsNumericType() && right->GetType()->IsNumericType())
return MaxType(left, right);
 
if (left ->GetType()->IsNumericType()) return right->GetType();
if (right->GetType()->IsNumericType()) return left ->GetType();
 
fprintf(stderr, "Illegal pointer arithmetic\n");
semantic_errors++;
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
TypeName * SubtractionExpression::SetType()
{
assert(left);
assert(right);
 
if (left->GetType()->IsNumericType() && right->GetType()->IsNumericType())
return MaxType(left, right);
 
if (left ->GetType()->IsNumericType()) return right->GetType();
if (right->GetType()->IsNumericType()) return left ->GetType();
 
// TODO: check pointer compatibility
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
TypeName * CondExpression::SetType()
{
// TODO: check argument compatibility
return right->GetType();
}
//-----------------------------------------------------------------------------
TypeName * ArgListExpression::SetType()
{
assert(0);
return 0;
}
//-----------------------------------------------------------------------------
void Expression::SetType(TypeName * t)
{
assert(!type_name);
type_name = t;
assert(type_name);
}
//-----------------------------------------------------------------------------
TypeName * Expression::GetType()
{
if (!type_name) type_name = SetType();
assert(type_name);
return type_name;
}
//-----------------------------------------------------------------------------
bool Expression::IsPointer()
{
return GetType()->IsPointer();
}
//-----------------------------------------------------------------------------
bool Expression::IsArray()
{
return GetType()->IsArray();
}
//-----------------------------------------------------------------------------
bool Expression::IsUnsigned()
{
return GetType()->IsUnsigned();
}
//-----------------------------------------------------------------------------
int Expression::PointeeSize()
{
return GetType()->GetPointeeSize();
}
//-----------------------------------------------------------------------------
int Expression::GetSize()
{
return GetType()->GetSize();
}
//-----------------------------------------------------------------------------
SUW Expression::GetSUW()
{
return GetType()->GetSUW();
}
//-----------------------------------------------------------------------------
void IdentifierExpression::Emit(FILE * out)
{
assert(this);
assert(varname);
EmitStart(out);
EmitIndent(out);
fprintf(out, "expr_type = \"identifier\" (%s)\n", varname);
 
const int spos = Name::FindPos(varname);
if (spos == 1)
{
fprintf(stderr, "Variable %s not declared\n", varname);
semantic_errors++;
}
else
{
if (spos == 0) Backend::load_rr_var(varname, GetSUW());
else Backend::load_rr_var(varname, spos, GetSUW());
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void IdentifierExpression::Emit_to_ll(FILE * out)
{
assert(this);
EmitStart(out);
EmitIndent(out);
fprintf(out, "expr_type = \"identifier\" (%s)\n", varname);
 
assert(varname);
const int spos = Name::FindPos(varname);
if (spos == 1)
{
fprintf(stderr, "Variable %s not declared\n", varname);
semantic_errors++;
}
else
{
if (spos == 0) Backend::load_ll_var(varname, GetSUW());
else Backend::load_ll_var(varname, spos, GetSUW());
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void StringExpression::Emit(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(string_constant);
string_constant->EmitValue_RR(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void StringExpression::EmitAddress(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(string_constant);
string_constant->EmitValue_RR(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void StringExpression::Emit_to_ll(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(string_constant);
string_constant->EmitValue_LL(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void NumericExpression::Emit(FILE * out)
{
assert(this);
assert(int_value);
EmitStart(out);
 
assert(int_value);
int_value->EmitValue_RR(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void NumericExpression::Emit_to_ll(FILE * out)
{
assert(this);
assert(int_value);
EmitStart(out);
 
assert(int_value);
int_value->EmitValue_LL(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void CondExpression::Emit(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(left);
assert(middle);
assert(right);
ExpressionStatement sm(middle);
ExpressionStatement sr(right);
IfElseStatement sel(left, &sm, &sr);
sel.Emit(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void BinaryExpression::EmitAddress(FILE * out)
{
assert(this);
assert(left);
EmitStart(out);
 
switch(expr_type)
{
case ET_ELEMENT: // expr[expr]
{
if (left->IsPointer())
{
assert(right);
right->Emit(out);
Backend::scale_rr(left->GetType()->GetPointeeSize());
Backend::push_rr(WO);
left->Emit(out);
Backend::pop_ll(WO);
Backend::compute_binary(ET_ADD, true, "+ (element)");
}
else if (left->IsArray())
{
assert(right);
right->Emit(out);
Backend::scale_rr(left->GetType()->GetPointeeSize());
left->AddAddress(out);
}
else
{
left->GetType()->Print(out);
fprintf(stderr, " is not a pointer\n");
semantic_errors++;
}
}
break;
 
default:
fprintf(stderr, "'expr %s expr' is not an lvalue\n",
GetPretty(expr_type));
semantic_errors++;
break;
}
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void UnaryExpression::EmitAddress(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(right);
switch(expr_type)
{
case ET_CAST: // (type) expr
case ET_CONJUGATE: // + expr
case ET_LOG_NOT: // ! expr
case ET_NEGATE: // - expr
case ET_COMPLEMENT: // ~ expr
fprintf(stderr, "'%s expr' is not an lvalue\n",
GetPretty(expr_type));
semantic_errors++;
break;
 
case ET_CONTENT: // * expr
right->Emit(out);
break;
 
case ET_ADDRESS: // & expr
right->EmitAddress(out);
break;
 
default: assert(0 && "Bad expr_type");
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void UnaryExpression::EmitInitialization(FILE * out, int size)
{
assert(this);
assert(right);
switch(expr_type)
{
case ET_CAST: // (type)expr
right->EmitInitialization(out, size);
return;
 
case ET_ADDRESS: // & expr
if (size != 2) right->Emit(stderr);
assert(size == 2);
if (right->IsVariable())
{
const char * vname = right->GetVarname();
assert(vname);
 
// check that var is declared
const int spos = Name::FindPos(vname);
if (spos == 1)
{
fprintf(stderr, "Variable %s not declared\n", vname);
semantic_errors++;
return;
}
 
fprintf(out, "\t.WORD\tC%s\t\t\t; & %s\n", vname, vname);
return;
}
}
 
fprintf(stderr, "Non-const initializer (not supported)\n");
semantic_errors++;
}
//-----------------------------------------------------------------------------
void UnaryExpression::Emit(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(right);
switch(expr_type)
{
case ET_PREINC:
case ET_PREDEC:
{
BinExprType op = ET_ADD;
const char * ops = "++";
if (expr_type == ET_PREDEC)
{
op = ET_SUB;
ops = "--";
}
 
int amount = 1;
if (right->IsPointer())
amount = right->GetType()->GetPointeeSize();
 
if (right->IsVariable())
{
right->Emit(out);
Backend::compute_binary(op, true, ops, amount);
right->EmitAssign(out);
break;
}
 
right->EmitAddress(out);
Backend::move_rr_to_ll();
Backend::content(right->GetSUW());
Backend::compute_binary(op, true, ops, amount);
Backend::assign(right->GetSUW());
}
break;
 
case ET_LOG_NOT: // ! expr
case ET_NEGATE: // - expr
case ET_COMPLEMENT: // ~ expr
right->Emit(out);
Backend::compute_unary(expr_type, GetPretty(expr_type));
break;
 
case ET_ADDRESS: // & expr
right->EmitAddress(out);
break;
 
case ET_CONTENT: // * expr
right->Emit(out);
Backend::content(GetSUW());
break;
 
case ET_CONJUGATE: // + expr
right->Emit(out);
break;
 
case ET_CAST: // (type) expr
right->Emit(out);
break;
 
default: assert(0 && "Bad expr_type");
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void BinaryExpression::Emit(FILE * out)
{
assert(this);
EmitStart(out);
((TypeName *)GetType())->Emit(out);
 
assert(left);
assert(right || expr_type == ET_FUNCALL); // zero if no args
switch(expr_type)
{
case ET_FUNCALL:
left ->EmitCall(out, right);
break;
 
case ET_LIST:
left ->Emit(out);
right->Emit(out);
break;
 
case ET_ASSIGN: // expr = expr
right->Emit(out);
if (left->IsVariable())
{
left->EmitAssign(out);
break;
}
Backend::push_rr(left->GetSUW());
left->EmitAddress(out);
Backend::move_rr_to_ll();
Backend::pop_rr(left->GetSUW());
Backend::assign(GetSize());
break;
 
case ET_BIT_OR: // expr | expr
case ET_BIT_AND: // expr & expr
case ET_BIT_XOR: // expr ^ expr
case ET_MULT: // expr * expr
case ET_DIV: // expr / expr
case ET_MOD: // expr % expr
case ET_LEFT: // expr << expr
case ET_RIGHT: // expr >> expr
case ET_EQUAL: // expr == expr
case ET_NOT_EQUAL: // expr != expr
case ET_LESS_EQUAL: // expr <= expr
case ET_LESS: // expr < expr
case ET_GREATER_EQUAL: // expr >= expr
case ET_GREATER: // expr > expr
if (right->IsConstant())
{
left->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(),
GetPretty(expr_type),
right->GetConstantNumericValue());
}
else if (left->IsConstant())
{
right->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(),
left->GetConstantNumericValue(),
GetPretty(expr_type));
}
else if (right->IsVariable())
{
left->Emit(out);
Backend::move_rr_to_ll();
right->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(),
GetPretty(expr_type));
}
else if (left->IsVariable())
{
right->Emit(out);
left->Emit_to_ll(out);
Backend::compute_binary(expr_type, IsUnsigned(),
GetPretty(expr_type));
}
else
{
left->Emit(out);
Backend::push_rr(WO);
right->Emit(out);
Backend::pop_ll(WO);
Backend::compute_binary(expr_type, IsUnsigned(),
GetPretty(expr_type));
}
break;
 
case ET_LOG_AND: // expr && expr
// if (left) right;
{
ExpressionStatement r(right);
IfElseStatement i(left, &r, 0);
i.Emit(out);
}
break;
 
case ET_LOG_OR: // expr || expr
// if (left) ; else right;
{
ExpressionStatement r(right);
IfElseStatement i(left, 0, &r);
i.Emit(out);
}
break;
 
case ET_ELEMENT: // expr [ expr ]
EmitAddress(out);
Backend::content(left->GetType()->ContentOf()->GetSUW());
break;
 
default: assert(0 && "Bad expr_type");
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void AdditionExpression::Emit(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(left);
assert(right);
 
Expression * lft = left;
Expression * rht = right;
 
// move pointer to left side
if (right->IsPointer() || right->IsArray())
{
lft = right;
rht = left;
}
 
if (rht->IsPointer() || rht->IsArray()) // error: pinter + pointer
{
fprintf(stderr, "Bad pointer arithmetic\n");
semantic_errors++;
EmitEnd(out);
return;
}
 
int rscale = 1;
if (lft ->IsPointer()) rscale = lft ->PointeeSize();
 
if (rht->IsConstant())
{
lft->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(), GetPretty(ET_ADD),
rscale * rht->GetConstantNumericValue());
EmitEnd(out);
return;
}
 
if (lft->IsConstant())
{
rht->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(),
lft->GetConstantNumericValue(),
GetPretty(ET_ADD));
EmitEnd(out);
return;
}
 
if (rht->IsVariable())
{
lft->Emit(out);
Backend::move_rr_to_ll();
rht->Emit(out);
}
else if (lft->IsVariable())
{
rht->Emit(out);
lft->Emit_to_ll(out);
}
else
{
rht->Emit(out);
Backend::push_rr(WO);
lft->Emit(out);
Backend::move_rr_to_ll();
Backend::pop_rr(WO);
}
 
Backend::scale_rr(rscale);
Backend::compute_binary(ET_ADD, IsUnsigned(), GetPretty(ET_ADD));
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void SubtractionExpression::Emit(FILE * out)
{
assert(this);
EmitStart(out);
 
assert(left);
assert(right);
 
int rscale = 1;
int uscale = 1;
if (left->IsPointer())
{
if (right->IsPointer()) uscale = left->PointeeSize();
else rscale = left->PointeeSize();
}
else if (right->IsPointer())
{
fprintf(stderr, "Bad pointer arithmetic\n");
semantic_errors++;
EmitEnd(out);
return;
}
 
if (left->IsConstant())
{
right->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(),
left->GetConstantNumericValue(),
GetPretty(ET_SUB));
EmitEnd(out);
return;
}
 
if (right->IsConstant())
{
left->Emit(out);
Backend::compute_binary(expr_type, IsUnsigned(), GetPretty(ET_SUB),
rscale * right->GetConstantNumericValue());
EmitEnd(out);
return;
}
 
if (right->IsVariable())
{
left->Emit(out);
Backend::move_rr_to_ll();
right->Emit(out);
}
else if (left->IsVariable())
{
right->Emit(out);
Backend::move_rr_to_ll();
left->Emit_to_ll(out);
}
else
{
right->Emit(out);
Backend::push_rr(WO);
left->Emit(out);
Backend::move_rr_to_ll();
Backend::pop_rr(WO);
}
 
Backend::scale_rr(rscale);
Backend::compute_binary(ET_SUB, IsUnsigned(), GetPretty(ET_SUB));
Backend::unscale_rr(uscale, right->IsUnsigned());
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
const char * Expression::GetPrettyName(const char * pretty)
{
assert(pretty);
const int plen = strlen(pretty);
char * ret = new char[plen + 10];
sprintf(ret, "Expr %s", pretty);
return ret;
}
//-----------------------------------------------------------------------------
const char * UnaryExpression::GetPretty(UnaExprType expr_type)
{
switch(expr_type)
{
case ET_ADDRESS: return "& r";
case ET_CAST: return "()r";
case ET_CONTENT: return "* r";
case ET_CONJUGATE: return "+ r";
case ET_NEGATE: return "- r";
case ET_COMPLEMENT: return "~ r";
case ET_LOG_NOT: return "! r";
case ET_POSTINC: return "r++";
case ET_POSTDEC: return "r--";
case ET_PREINC: return "++r";
case ET_PREDEC: return "--r";
 
default: return "BAD UNARY EXPR_TYPE";
}
}
//-----------------------------------------------------------------------------
const char * BinaryExpression::GetPretty(BinExprType expr_type)
{
switch(expr_type)
{
case ET_LIST: return "l , r";
case ET_ARGLIST: return "(l , r)";
case ET_ASSIGN: return "l = r";
case ET_MULT_ASSIGN: return "l *- r";
case ET_DIV_ASSIGN: return "l /= r";
case ET_MOD_ASSIGN: return "l %= r";
case ET_ADD_ASSIGN: return "l += r";
case ET_SUB_ASSIGN: return "l -= r";
case ET_LEFT_ASSIGN: return "l <<= r";
case ET_RIGHT_ASSIGN: return "l >>= r";
case ET_AND_ASSIGN: return "l & r";
case ET_XOR_ASSIGN: return "l ^ r";
case ET_OR_ASSIGN: return "l | r";
case ET_LOG_OR: return "l || r";
case ET_LOG_AND: return "l && r";
case ET_BIT_OR: return "l | r";
case ET_BIT_AND: return "l & r";
case ET_BIT_XOR: return "l ^ r";
case ET_EQUAL: return "l == r";
case ET_NOT_EQUAL: return "l != r";
case ET_LESS_EQUAL: return "l <= r";
case ET_LESS: return "l < r";
case ET_GREATER_EQUAL: return "l >= r";
case ET_GREATER: return "l > r";
case ET_LEFT: return "l << r";
case ET_RIGHT: return "l >> r";
case ET_ADD: return "l + r";
case ET_SUB: return "l - r";
case ET_MULT: return "l * r";
case ET_DIV: return "l / r";
case ET_MOD: return "l % r";
case ET_FUNCALL: return "l(r)";
case ET_ELEMENT: return "l[r]";
 
default: return "BAD BINARY EXPR_TYPE";
}
}
//-----------------------------------------------------------------------------
void IdentifierExpression::EmitAssign(FILE * out)
{
assert(varname);
const int spos = Name::FindPos(varname);
if (spos == 1)
{
fprintf(stderr, "Variable %s not declared\n", varname);
semantic_errors++;
return;
}
 
if (spos == 0) Backend::store_rr_var(varname, GetSUW());
else Backend::store_rr_var(varname, spos, GetSUW());
}
//-----------------------------------------------------------------------------
void IdentifierExpression::AddAddress(FILE * out)
{
assert(varname);
const int spos = Name::FindPos(varname);
if (spos == 1)
{
fprintf(stderr, "Variable %s not declared\n", varname);
semantic_errors++;
return;
}
 
if (spos == 0) Backend::add_address(varname);
else Expression::AddAddress(out);
}
//-----------------------------------------------------------------------------
void IdentifierExpression::EmitAddress(FILE * out)
{
assert(varname);
const int spos = Name::FindPos(varname);
if (spos == 1)
{
fprintf(stderr, "Variable %s not declared\n", varname);
semantic_errors++;
return;
}
 
if (spos == 0) Backend::load_address(varname);
else Backend::load_address(varname, spos);
}
//-----------------------------------------------------------------------------
void IdentifierExpression::EmitInitialization(FILE * out, int size)
{
assert(varname);
fprintf(out, "\t.WORD\tC%s\n", varname);
}
//-----------------------------------------------------------------------------
void Expression::EmitInitialization(FILE * out, int size)
{
fprintf(stderr, "TODO: EmitInitialization %s\n", GetNodeType());
Emit(stderr);
fprintf(stderr, "----: EmitInitialization %s\n", GetNodeType());
assert(0);
}
//-----------------------------------------------------------------------------
void Expression::EmitAddress(FILE * out)
{
fprintf(stderr, "TODO: Expression::EmitAddress() %s\n", GetNodeType());
Emit(stderr);
fprintf(stderr, "----: Expression::EmitAddress() %s\n", GetNodeType());
assert(0);
}
//-----------------------------------------------------------------------------
void Expression::AddAddress(FILE * out)
{
Backend::push_rr(WO);
Emit(out);
Backend::pop_ll(WO);
Backend::compute_binary(ET_ADD, true, "&l[r]");
}
//-----------------------------------------------------------------------------
BinExprType BinaryExpression::MapAssign(BinExprType et)
{
switch(et)
{
case ET_MULT_ASSIGN: return ET_MULT;
case ET_DIV_ASSIGN: return ET_DIV;
case ET_MOD_ASSIGN: return ET_MOD;
case ET_LEFT_ASSIGN: return ET_LEFT;
case ET_RIGHT_ASSIGN: return ET_RIGHT;
case ET_AND_ASSIGN: return ET_BIT_AND;
case ET_XOR_ASSIGN: return ET_BIT_XOR;
case ET_OR_ASSIGN: return ET_BIT_OR;
}
 
assert(0 && "Bad expr_type");
}
//-----------------------------------------------------------------------------
int Expression::FunReturnSize()
{
TypeName * funtn = FunReturnType();
assert(funtn);
 
return funtn->GetFunReturnSize();
}
//-----------------------------------------------------------------------------
TypeName * Expression::FunReturnType()
{
TypeName * tn = GetType();
assert(tn);
return tn->GetFunReturnType();
}
//-----------------------------------------------------------------------------
Expression * IdentifierExpression::New(const char * s)
{
int value;
bool is_enum = Name::FindEnum(s, value);
 
if (!is_enum) return new IdentifierExpression(s);
 
int spos = Name::FindPos(s);
 
if (spos != 1)
{
fprintf(stderr, "Warning: variable %s shadows enum value\n", s);
return new IdentifierExpression(s);
}
 
return new NumericExpression(value);
}
//-----------------------------------------------------------------------------
TypeName * IdentifierExpression::FunReturnType()
{
assert(varname);
 
TypeName * funtn = Name::FindType(varname);
if (funtn) return funtn->GetFunReturnType();
 
fprintf(stderr, "Function '%s' not declared\n", varname);
semantic_errors++;
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
TypeName * BinaryExpression::MaxType(Expression * left, Expression * right)
{
TypeName * ltype = left ->GetType(); assert(ltype);
TypeName * rtype = right->GetType(); assert(rtype);
 
if (!ltype->IsNumericType())
{
if ( expr_type == ET_EQUAL || expr_type == ET_NOT_EQUAL
|| expr_type == ET_LESS_EQUAL || expr_type == ET_LESS
|| expr_type == ET_GREATER_EQUAL || expr_type == ET_GREATER)
{
if (ltype->IsPointer()) return ltype;
}
 
fprintf(stderr, "Left argument of %s is not numeric\n",
GetPretty(expr_type));
semantic_errors++;
return new TypeName(TS_INT);
}
 
if (!rtype->IsNumericType())
{
if ( expr_type == ET_EQUAL || expr_type == ET_NOT_EQUAL
|| expr_type == ET_LESS_EQUAL || expr_type == ET_LESS
|| expr_type == ET_GREATER_EQUAL || expr_type == ET_GREATER)
{
if (rtype->IsPointer()) return rtype;
}
 
fprintf(stderr, "Right argument of %s is not numeric\n",
GetPretty(expr_type));
semantic_errors++;
return new TypeName(TS_INT);
}
 
Specifier spec = TS_INT;
 
if (ltype->IsUnsigned()) spec = (Specifier)(TS_INT | TS_UNSIGNED);
if (rtype->IsUnsigned()) spec = (Specifier)(TS_INT | TS_UNSIGNED);
return new TypeName(spec);
}
//-----------------------------------------------------------------------------
int NumericExpression::GetConstantNumericValue() const
{
assert(int_value);
return int_value->GetValue();
}
//-----------------------------------------------------------------------------
int Expression::GetConstantNumericValue() const
{
fprintf(stderr, "Non-constant value where numeric constant expected\n");
semantic_errors++;
return 0;
}
//-----------------------------------------------------------------------------
StringConstant * Expression::GetStringConstant() const
{
fprintf(stderr, "Non-constant value where string constant expected\n");
semantic_errors++;
return 0;
}
//-----------------------------------------------------------------------------
void Expression::EmitCall(FILE * out, Expression * args)
{
TypeName * tname;
 
tname = GetType();
assert(tname);
 
ParameterDeclarationList * plist = tname->GetParameters();
 
int param_bytes_pushed = 0;
if (args)
{
if (!plist)
{
const char * funname = GetVarname();
if (funname == 0) funname = "";
fprintf(stderr,
"Arguments for function %s without parameters\n",
funname);
semantic_errors++;
return;
}
param_bytes_pushed += args->EmitPush(out, plist);
}
else
{
if (plist)
{
const char * funname = GetVarname();
if (funname == 0) funname = "";
fprintf(stderr,
"No arguments for function %s with parameters\n",
funname);
semantic_errors++;
return;
}
}
 
// compute return value size
const int ret_size = tname->GetFunReturnSize();
param_bytes_pushed += Backend::push_return(ret_size);
 
if (GetType()->IsFunPtr())
{
Emit(out);
Backend::call_ptr();
}
else
{
assert(GetVarname());
Backend::call(GetVarname());
}
 
Backend::pop(param_bytes_pushed);
}
//-----------------------------------------------------------------------------
int ArgListExpression::EmitPush(FILE * out, ParameterDeclarationList * args)
{
EmitStart(out);
 
assert(left);
assert(right);
 
ParameterDeclarationList * a = args;
for (int l = left->GetParaLength(); a && l; l--)
{
if (!a->Head()->IsEllipsis()) a = a->Tail();
}
 
if (a)
{
const int rpush = right->EmitPush(out, a);
const int lpush = left ->EmitPush(out, args);
 
EmitEnd(out);
return rpush + lpush;
}
 
fprintf(stderr, "Too many arguments\n");
semantic_errors++;
EmitEnd(out);
return 0;
}
//-----------------------------------------------------------------------------
int Expression::EmitPush(FILE * out, ParameterDeclarationList * args)
{
assert(args);
 
ParameterDeclaration * pd = args->Head();
assert(pd);
 
TypeName * tname = pd->GetTypeName();
assert(tname);
 
SUW suw;
 
pd->Emit(out); // just shows type
if (tname->IsPointer() && GetType()->IsArray())
{
EmitAddress(out);
suw = WO;
}
else
{
Emit(out);
suw = tname->GetSUW();
}
 
Backend::push_rr(suw);
 
if (suw == WO) return 2;
return 1;
}
//-----------------------------------------------------------------------------
int ArgListExpression::GetParaLength() const
{
assert(left);
assert(right);
 
return left->GetParaLength() + right->GetParaLength();
}
//-----------------------------------------------------------------------------
AsmExpression::AsmExpression(StringConstant * string)
: Expression("asm Expression")
{
asm_string = string->Kill();
assert(asm_string);
}
//-----------------------------------------------------------------------------
void AsmExpression::Emit(FILE * out)
{
Backend::asmbl(asm_string);
}
//-----------------------------------------------------------------------------
TypeName * AsmExpression::SetType()
{
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
/Node.hh
0,0 → 1,1056
// Node.hh
#ifndef __NODE_HH_DEFINED__
#define __NODE_HH_DEFINED__
 
#include <assert.h>
#include "List.hh"
 
//-----------------------------------------------------------------------------
 
class TypeSpecifier;
class DeclItem;
class Initializer;
class TypeName;
class Expression;
 
const char * GetDeclaredName(Declarator * decl);
ParameterDeclarationList * GetParameters(Declarator * decl);
bool IsFunPtr(Declarator * decl);
bool IsPointer(Declarator * decl);
Expression * ArrayLength(Declarator * decl);
void SetArrayLength(Declarator * decl, int len);
bool IsFunction(Declarator * decl);
bool IsArray(Declarator * decl);
 
enum SUW { SB, UB, WO };
 
//-----------------------------------------------------------------------------
class Constant : public Node
{
public:
Constant(const char * name)
: Node(name)
{};
 
virtual void EmitValue_RR(FILE * out) = 0;
virtual void EmitValue_LL(FILE * out) = 0;
};
//-----------------------------------------------------------------------------
class NumericConstant : public Constant
{
public:
NumericConstant(const char * txt);
NumericConstant(int val, int siz = 0)
: Constant("NumericConstant"),
value(val),
size(siz)
{};
 
virtual void EmitValue_RR(FILE * out);
virtual void EmitValue_LL(FILE * out);
int GetValue() const { return value; };
int GetSize() const { return size; };
 
void Negate() { value = -value; };
void Complement() { value = ~value; };
void LogNot() { if (value) value = 0; else value = -1; };
 
private:
int value;
int size;
};
//-----------------------------------------------------------------------------
class StringConstant : public Constant
{
public:
StringConstant();
~StringConstant();
 
virtual void EmitValue_RR(FILE * out);
virtual void EmitValue_LL(FILE * out);
void operator += (char txt);
StringConstant * operator & (StringConstant * other);
void operator += (const char * txt)
{ while (*txt) *this += *txt++; };
 
int GetStringNumber() const { return string_number; };
int GetLength() const { return value_len; };
char * Kill()
{ char * ret = buffer; buffer = 0; delete this; return ret; };
 
void EmitAndRemove(FILE * out, int length);
 
static void EmitAll(FILE * out);
 
private:
char * buffer;
int buffer_len;
int value_len;
int string_number;
 
static int str_count;
enum { MAX_STRINGS = 5000 };
static StringConstant * all_strings[MAX_STRINGS];
};
//-----------------------------------------------------------------------------
// how an expression is created...
// //
enum BinExprType
{
// binary
ET_LIST, // expr , expr
ET_ARGLIST, // expr , expr in function argument
ET_ASSIGN, // expr = expr
ET_MULT_ASSIGN, // expr *= expr
ET_DIV_ASSIGN, // expr /= expr
ET_MOD_ASSIGN, // expr %= expr
ET_ADD_ASSIGN, // expr += expr
ET_SUB_ASSIGN, // expr -= expr
ET_LEFT_ASSIGN, // expr <<= expr
ET_RIGHT_ASSIGN, // expr >>= expr
ET_AND_ASSIGN, // expr &= expr
ET_XOR_ASSIGN, // expr ^= expr
ET_OR_ASSIGN, // expr |= expr
ET_BIT_OR, // expr | expr
ET_BIT_AND, // expr & expr
ET_BIT_XOR, // expr ^ expr
ET_LOG_OR, // expr || expr
ET_LOG_AND, // expr && expr
ET_EQUAL, // expr == expr
ET_NOT_EQUAL, // expr != expr
ET_LESS_EQUAL, // expr <= expr
ET_LESS, // expr < expr
ET_GREATER_EQUAL, // expr >= expr
ET_GREATER, // expr > expr
ET_LEFT, // expr << expr
ET_RIGHT, // expr >> expr
ET_ADD, // expr + expr
ET_SUB, // expr - expr
ET_MULT, // expr * expr
ET_DIV, // expr / expr
ET_MOD, // expr % expr
ET_ELEMENT, // expr [ expr ]
ET_FUNCALL // expr ( ... )
};
 
enum UnaExprType
{
ET_CAST, // (type) expr
ET_ADDRESS, // & expr
ET_CONTENT, // * expr
ET_CONJUGATE, // + expr
ET_NEGATE, // - expr
ET_COMPLEMENT, // ~ expr
ET_LOG_NOT, // ! expr
ET_POSTINC, // ++ expr
ET_POSTDEC, // -- expr
ET_PREINC, // ++ expr
ET_PREDEC // -- expr
};
 
class Expression : public Node
{
public:
Expression(const char * nodename)
: Node(nodename),
type_name(0)
{};
 
virtual void Emit(FILE * out) = 0;
virtual void Emit_to_ll(FILE * out) { assert(0); };
void EmitCall(FILE * out, Expression * right);
virtual void EmitInitialization(FILE * out, int size);
virtual void EmitAddress(FILE * out);
virtual void AddAddress(FILE * out);
virtual int EmitPush(FILE * out, ParameterDeclarationList * params);
virtual void EmitAssign(FILE * out) { assert(0); };
virtual int GetParaLength() const { return 1; };
 
virtual bool IsConstant() const { return false; };
virtual bool IsNumericConstant() const { return false; };
virtual bool IsStringConstant() const { return false; };
virtual bool IsVariable() const { return false; };
virtual const char * GetVarname() const { return 0; };
virtual int GetConstantNumericValue() const;
virtual StringConstant * GetStringConstant() const;
virtual TypeName * FunReturnType();
virtual TypeName * SetType() = 0;
virtual SUW GetSUW();
void SetType(TypeName * t);
 
bool IsPointer();
bool IsArray();
int PointeeSize();
int GetSize();
TypeName * GetType();
bool IsUnsigned();
int FunReturnSize();
 
static const char * GetPrettyName(const char * pretty);
 
virtual Expression * OptNegate() { assert(0); };
virtual Expression * OptComplement() { assert(0); };
virtual Expression * OptLogNot() { assert(0); };
 
private:
TypeName * type_name;
};
//-----------------------------------------------------------------------------
class IdentifierExpression : public Expression
{
public:
static Expression * New(const char * s);
 
virtual void Emit(FILE * out);
virtual void EmitAssign(FILE * out);
virtual void Emit_to_ll(FILE * out);
virtual TypeName * SetType();
 
virtual bool IsVariable() const { return true; };
virtual const char * GetVarname() const { return varname; };
virtual void EmitAddress(FILE * out);
virtual void EmitInitialization(FILE * out, int size);
virtual void AddAddress(FILE * out);
virtual TypeName * FunReturnType();
 
private:
IdentifierExpression(const char * s)
: Expression("Expression (variable name)"),
varname(s)
{};
 
const char * varname;
};
//-----------------------------------------------------------------------------
class MemberExpression : public Expression
{
public:
MemberExpression(bool is_pointer, Expression * r, const char * s);
 
virtual void Emit(FILE * out);
virtual void EmitAddress(FILE * out);
void EmitAddress(FILE * out, bool content);
virtual TypeName * SetType();
 
private:
Expression * left;
const char * membername;
};
//-----------------------------------------------------------------------------
class StringExpression : public Expression
{
public:
StringExpression(StringConstant * s);
 
virtual void Emit(FILE * out);
virtual void EmitAddress(FILE * out);
virtual void Emit_to_ll(FILE * out);
virtual TypeName * SetType();
virtual void EmitInitialization(FILE * out, int size);
 
virtual bool IsConstant() const { return true; };
virtual bool IsStringConstant() const { return true; };
virtual StringConstant * GetStringConstant() const
{ return string_constant; }
 
private:
StringConstant * string_constant;
};
//-----------------------------------------------------------------------------
class NumericExpression : public Expression
{
public:
NumericExpression(NumericConstant * n);
NumericExpression(TypeName * t);
NumericExpression(Expression * r);
NumericExpression(int value);
 
virtual void Emit(FILE * out);
virtual void Emit_to_ll(FILE * out);
virtual bool IsConstant() const { return true; };
virtual bool IsNumericConstant() const { return true; };
virtual int GetConstantNumericValue() const;
virtual TypeName * SetType();
virtual void EmitInitialization(FILE * out, int size);
static const char * GetPretty(int value);
 
virtual Expression * OptNegate();
virtual Expression * OptComplement();
virtual Expression * OptLogNot();
 
private:
NumericConstant * int_value;
};
//-----------------------------------------------------------------------------
class CondExpression : public Expression
{
public:
CondExpression(Expression * l, Expression * m, Expression * r)
: Expression("Expression (l ? m : r)"),
left(l),
middle(m),
right(r)
{};
 
virtual void Emit(FILE * out);
virtual TypeName * SetType();
 
private:
Expression * left;
Expression * middle;
Expression * right;
};
//-----------------------------------------------------------------------------
class BinaryExpression : public Expression
{
public:
static Expression * New(BinExprType et, Expression * l, Expression * r);
 
virtual void Emit(FILE * out);
virtual TypeName * SetType();
virtual void EmitAddress(FILE * out);
 
TypeName * MaxType(Expression * l, Expression * r);
 
static const char * GetPretty(BinExprType expr_type);
static BinExprType MapAssign(BinExprType et);
 
protected:
BinaryExpression(BinExprType et, Expression * l, Expression * r);
BinExprType expr_type;
Expression * left;
Expression * right;
};
//-----------------------------------------------------------------------------
class ArgListExpression : public BinaryExpression
{
public:
ArgListExpression(Expression * l, Expression * r)
: BinaryExpression(ET_ARGLIST, l, r)
{};
 
virtual void Emit(FILE * out) {}; // done vy EmitPush()
virtual int EmitPush(FILE * out, ParameterDeclarationList * params);
virtual int GetParaLength() const;
virtual TypeName * SetType();
};
//-----------------------------------------------------------------------------
class AdditionExpression : public BinaryExpression
{
public:
static Expression * New(Expression * l, Expression * r);
 
virtual void Emit(FILE * out);
virtual TypeName * SetType();
 
private:
AdditionExpression(Expression * l, Expression * r)
: BinaryExpression(ET_ADD, l, r)
{};
};
//-----------------------------------------------------------------------------
class SubtractionExpression : public BinaryExpression
{
public:
static Expression * New(Expression * l, Expression * r);
 
virtual void Emit(FILE * out);
virtual TypeName * SetType();
 
private:
SubtractionExpression(Expression * l, Expression * r)
: BinaryExpression(ET_SUB, l, r)
{};
};
//-----------------------------------------------------------------------------
class UnaryExpression : public Expression
{
public:
UnaryExpression(TypeName * t, Expression * r);
 
virtual void Emit(FILE * out);
virtual void EmitAddress(FILE * out);
virtual void EmitInitialization(FILE * out, int size);
virtual TypeName * SetType();
 
static const char * GetPretty(UnaExprType expr_type);
static Expression * New(UnaExprType et, Expression * r);
 
private:
UnaryExpression(UnaExprType et, Expression * r)
: Expression(GetPrettyName(GetPretty(et))),
expr_type(et),
right(r)
{};
 
UnaExprType expr_type;
Expression * right;
};
//-----------------------------------------------------------------------------
class AsmExpression : public Expression
{
public:
AsmExpression(StringConstant * string);
 
virtual void Emit(FILE * out);
virtual TypeName * SetType();
 
private:
char * asm_string;
};
//-----------------------------------------------------------------------------
enum Specifier
{
// storage class
SC_TYPEDEF = 0x00000001,
SC_EXTERN = 0x00000002,
SC_STATIC = 0x00000004,
SC_AUTO = 0x00000008,
SC_REGISTER = 0x00000010,
SC_MASK = SC_TYPEDEF | SC_EXTERN | SC_STATIC | SC_AUTO | SC_REGISTER,
 
// type qualifiers
TQ_CONST = 0x00000100,
TQ_VOLATILE = 0x00000200,
TQ_MASK = TQ_CONST | TQ_VOLATILE,
 
// type specifiers
TS_SIGNED = 0x00001000,
TS_UNSIGNED = 0x00002000,
TS_SIGN_MASK = TS_SIGNED | TS_UNSIGNED,
 
TS_VOID = 0x00010000,
TS_CHAR = 0x00020000,
TS_SHORT = 0x00040000,
TS_INT = 0x00080000,
TS_LONG = 0x00100000,
TS_FLOAT = 0x00200000,
TS_DOUBLE = 0x00400000,
TS_STRUCT = 0x00800000,
TS_UNION = 0x01000000,
TS_ENUM = 0x02000000,
TS_TYPE_NAME = 0x04000000,
TS_MASK = TS_VOID | TS_CHAR | TS_SHORT | TS_INT | TS_LONG |
TS_FLOAT | TS_DOUBLE | TS_STRUCT |
TS_UNION | TS_ENUM | TS_TYPE_NAME,
TS_NUMERIC = TS_CHAR | TS_SHORT | TS_INT | TS_LONG |
TS_FLOAT | TS_DOUBLE | TS_ENUM,
};
//-----------------------------------------------------------------------------
class Ptr : public Node
{
public:
Ptr(TypeSpecifier * ds)
: Node("Ptr"),
decl_specs(ds)
{};
 
virtual void Emit(FILE * out);
int Print(FILE * out) const;
private:
TypeSpecifier * decl_specs;
};
//-----------------------------------------------------------------------------
class Identifier : public Node
{
public:
Identifier(const char * n)
: Node("Identifier"),
name(n)
{};
 
private:
const char * name;
};
//-----------------------------------------------------------------------------
class Initializer : public Node
{
public:
Initializer(Expression * expr)
: Node("Initializer (skalar)"),
skalar_value(expr),
array_value(0)
{};
 
Initializer(InitializerList * list)
: Node("Initializer (vector)"),
skalar_value(0),
array_value(list)
{};
 
virtual void Emit(FILE * out);
virtual void EmitValue(FILE * out, TypeName * tn);
 
int InitAutovar(FILE * out, SUW suw);
private:
Expression * skalar_value;
InitializerList * array_value;
};
//-----------------------------------------------------------------------------
class ParameterDeclaration : public Node
{
public:
ParameterDeclaration(TypeSpecifier * ds, Declarator * dec);
 
virtual void Emit(FILE * out);
 
int AllocateParameters(int position);
const char * GetDeclaredName(int skip);
TypeName * GetTypeName() const { return type; };
bool IsEllipsis() const { return isEllipsis; };
ParameterDeclaration * SetEllipsis() { isEllipsis = true; return this; };
private:
TypeName * type;
bool isEllipsis;
};
//-----------------------------------------------------------------------------
enum DECL_WHAT
{
DECL_NAME = 1,
DECL_FUNPTR = 2,
DECL_ARRAY = 3,
DECL_FUN = 4,
DECL_POINTER = 5
};
 
class DeclItem : public Node
{
public:
DeclItem(DECL_WHAT w)
: Node("DeclItem"),
what(w),
name(0),
funptr(0),
array_size(0),
fun_params(0),
fun_identifiers(0),
pointer(0)
{};
 
DeclItem(const char * n)
: Node("DeclItem"),
what(DECL_NAME),
name(n),
funptr(0),
array_size(0),
fun_params(0),
fun_identifiers(0),
pointer(0)
{};
 
DeclItem(Declarator * fp)
: Node("DeclItem"),
what(DECL_FUNPTR),
name(0),
funptr(fp),
array_size(0),
fun_params(0),
fun_identifiers(0),
pointer(0)
{};
 
DeclItem(Expression * ep)
: Node("DeclItem"),
what(DECL_ARRAY),
name(0),
funptr(0),
array_size(ep),
fun_params(0),
fun_identifiers(0),
pointer(0)
{};
 
DeclItem(ParameterDeclarationList * pl)
: Node("DeclItem"),
what(DECL_FUN),
name(0),
funptr(0),
array_size(0),
fun_params(pl),
fun_identifiers(0),
pointer(0)
{};
 
DeclItem(IdentifierList * il)
: Node("DeclItem"),
what(DECL_FUN),
name(0),
funptr(0),
array_size(0),
fun_params(0),
fun_identifiers(il),
pointer(0)
{};
 
DeclItem(Pointer * p)
: Node("DeclItem"),
what(DECL_POINTER),
name(0),
funptr(0),
array_size(0),
fun_params(0),
fun_identifiers(0),
pointer(p)
{};
 
virtual void Emit(FILE * out);
int Print(FILE * out) const;
const char * GetName() const { return name; };
DECL_WHAT GetWhat() const { return what; };
Declarator * GetFunptr() const { return funptr; };
Pointer * GetPointer() const { return pointer; };
Expression * GetArraySize() const { return array_size; };
void SetArraySize(int n);
ParameterDeclarationList * GetParameters() const { return fun_params; };
 
private:
const DECL_WHAT what;
const char * name;
Declarator * funptr;
Expression * array_size;
ParameterDeclarationList * fun_params;
IdentifierList * fun_identifiers;
Pointer * pointer;
};
//-----------------------------------------------------------------------------
class Enumerator : public Node
{
public:
Enumerator(const char * n, Expression * v)
: Node("Enumerator"),
name(n),
value(v)
{};
 
virtual void Emit(FILE * out);
static int current;
 
private:
const char * name;
Expression * value;
};
//-----------------------------------------------------------------------------
class StructDeclarator : public Node
{
public:
StructDeclarator(Declarator * dcl, Expression * exp)
: Node("StructDeclarator"),
declarator(dcl),
expression(exp),
position(-1)
{};
 
virtual void Emit(FILE * out);
int EmitMember(FILE * out, const char * struct_name,
TypeSpecifier * tspec, int pos, bool is_union);
TypeName * GetMemberType(TypeSpecifier * tspec, const char * member);
int GetMemberPosition(const char * member) const;
Declarator * GetDeclarator() const { return declarator; };
TypeName * FirstUnionMember(TypeSpecifier * tspec, int union_size) const;
const char * GetMemberName() const;
 
private:
Declarator * declarator;
Expression * expression; // : bitfield
int position;
};
//-----------------------------------------------------------------------------
class StructDeclaration : public Node
{
public:
StructDeclaration(TypeSpecifier * ds, StructDeclaratorList * sdl)
: Node("StructDeclaration"),
decl_specifiers(ds),
struct_decl_list(sdl),
size(-1)
{ };
 
int Emit(FILE * out, const char * struct_name, int pos, bool is_union);
TypeName * GetMemberType(const char * struct_name, const char * member);
int GetMemberPosition(const char * struct_name,
const char * member, bool is_union) const;
int GetSize() const { assert(size != -1); return size; };
 
TypeSpecifier * GetSpecifier() const { return decl_specifiers; };
StructDeclaratorList * GetDeclarators() const { return struct_decl_list; };
TypeName * FirstUnionMember(int size) const;
 
private:
TypeSpecifier * decl_specifiers;
StructDeclaratorList * struct_decl_list;
int size;
};
//-----------------------------------------------------------------------------
class TypeSpecifier : public Node
{
public:
// all types
TypeSpecifier(Specifier sp)
: Node("TypeSpecifier (all)"),
spec(sp),
name(0),
struct_decl_list(0),
enum_list(0)
{};
 
// structs, unions, typedef(name)
TypeSpecifier(Specifier sp, const char * n, StructDeclarationList * sdl);
 
// enums
TypeSpecifier(const char * n, EnumeratorList * el)
: Node("TypeSpecifier (enum)"),
spec(TS_ENUM),
name(n),
struct_decl_list(0),
enum_list(el)
{};
 
virtual void Emit(FILE * out);
int Print(FILE * out) const;
 
TypeSpecifier * operator +(TypeSpecifier & other);
TypeSpecifier * self() { return this; };
 
Specifier GetType() const { return spec; };
const char * GetName() const { return name; };
StructDeclarationList * GetStructDecl() const
{ return struct_decl_list; };
bool IsUnsigned() const { return spec & TS_UNSIGNED; };
 
int GetFunReturnSize(Declarator * decl) const;
int GetSize(Declarator * decl) const;
int GetBaseSize() const;
TypeName * GetMemberType(const char * member);
bool IsNumericType() const; // char, short, or int
bool IsUnion() const
{ if (spec & TS_UNION) return true; return false; };
bool IsStruct() const
{ if (spec & TS_STRUCT) return true; return false; };
 
private:
Specifier spec; // all types
const char * name; // enums, structs and unions
StructDeclarationList * struct_decl_list; // structs and unions
EnumeratorList * enum_list; // enums
 
static int anonymous_number;
};
//-----------------------------------------------------------------------------
class InitDeclarator : public Node
{
public:
InitDeclarator(Declarator * decl, Initializer * init)
: Node("InitDeclarator"),
declarator(decl),
initializer(init)
{};
 
virtual void Emit(FILE * out);
 
Declarator * GetDeclarator() const { return declarator; };
 
const char * GetDeclaredName(int skip);
void Allocate(FILE * out, TypeSpecifier * spec);
int EmitAutovars(FILE * out, TypeSpecifier * spec);
private:
Declarator * declarator;
Initializer * initializer;
};
//-----------------------------------------------------------------------------
class Declaration : public Node
{
public:
Declaration(TypeSpecifier * ds, InitDeclaratorList * il);
 
virtual void Emit(FILE * out);
 
void Allocate(FILE * out);
int EmitAutovars(FILE * out);
 
private:
TypeSpecifier * base_type;
InitDeclaratorList * init_list;
};
//-----------------------------------------------------------------------------
class TypeName : public Node
{
public:
TypeName(TypeSpecifier * ds, Declarator * ad);
TypeName(Specifier sp);
 
virtual void Emit(FILE * out);
int Print(FILE * out) const;
 
Declarator * GetDeclarator() const { return abs_declarator; };
TypeSpecifier * GetTypeSpecifier() const { return decl_spec; };
const char * GetDeclaredName();
TypeName * GetFunReturnType();
 
TypeName * AddressOf() const;
TypeName * ContentOf() const;
TypeName * GetElementType() const;
bool IsNumericType() const; // char, short, or int
bool IsPointer() const;
Expression * ArrayLength() const;
void SetArrayLength(int len);
bool IsStruct() const;
bool IsUnion() const;
bool IsArray() const;
int GetPointeeSize() const;
TypeName * GetMemberType(const char * member);
TypeName * FirstUnionMember(int size) const;
 
int GetFunReturnSize()
{ return decl_spec->GetFunReturnSize(abs_declarator); };
int GetSize() const
{ return decl_spec->GetSize(abs_declarator); };
SUW GetSUW();
bool IsUnsigned() const;
bool IsFunPtr() const
{ return ::IsFunPtr(abs_declarator); };
ParameterDeclarationList * GetParameters() const
{ return ::GetParameters(abs_declarator); };
 
private:
TypeSpecifier * decl_spec;
Declarator * abs_declarator;
};
//-----------------------------------------------------------------------------
class Statement : public Node
{
public:
Statement(const char * ntype)
: Node(ntype)
{};
 
virtual void Emit(FILE * out) = 0;
virtual bool NotEmpty() const { return true; };
virtual bool EmitCaseJump(FILE * out, bool def, int loop, int size)
{ return false; };
};
//-----------------------------------------------------------------------------
class LabelStatement : public Statement
{
public:
LabelStatement(const char * n, Statement * stat)
: Statement("Label Statement"),
label_name(n),
statement(stat)
{};
 
virtual void Emit(FILE * out);
 
private:
const char * label_name;
Statement * statement;
};
//-----------------------------------------------------------------------------
class CaseStatement : public Statement
{
public:
CaseStatement(Expression * exp, Statement * stat)
: Statement("case Statement"),
case_value(exp),
statement(stat)
{};
 
virtual void Emit(FILE * out);
virtual bool EmitCaseJump(FILE * out, bool def, int loop, int size);
 
private:
Expression * case_value; // case, or 0 for default
Statement * statement;
};
//-----------------------------------------------------------------------------
class CompoundStatement : public Statement
{
public:
CompoundStatement(DeclarationList * dl, StatementList * sl)
: Statement("CompoundStatement"),
decl_list(dl),
stat_list(sl)
{};
 
virtual void Emit(FILE * out);
virtual bool NotEmpty() const { return decl_list || stat_list; };
void EmitCaseJumps(FILE * out, int size);
 
int EmitAutovars(FILE * out);
private:
DeclarationList * decl_list;
StatementList * stat_list;
};
//-----------------------------------------------------------------------------
class ExpressionStatement : public Statement
{
public:
ExpressionStatement(Expression * expr)
: Statement("ExpressionStatement"),
expression(expr)
{};
virtual void Emit(FILE * out);
virtual bool NotEmpty() const { return expression; };
 
Expression * GetExpression() const { return expression; };
private:
Expression * expression;
};
//-----------------------------------------------------------------------------
class SwitchStatement : public Statement
{
public:
SwitchStatement(Expression * cond, CompoundStatement * cas)
: Statement("SwitchStatement"),
condition(cond),
case_stat(cas)
{};
 
virtual void Emit(FILE * out);
private:
Expression * condition;
CompoundStatement * case_stat;
};
//-----------------------------------------------------------------------------
class IfElseStatement : public Statement
{
public:
IfElseStatement(Expression * cond, Statement * ifs, Statement * els)
: Statement("IfElseStatement"),
condition(cond),
if_stat(ifs),
else_stat(els)
{};
 
virtual void Emit(FILE * out);
private:
Expression * condition;
Statement * if_stat;
Statement * else_stat;
};
//-----------------------------------------------------------------------------
class DoWhileStatement : public Statement
{
public:
DoWhileStatement(Statement * bdy, Expression * cond)
: Statement("do while Statement"),
condition(cond),
body(bdy)
{};
 
virtual void Emit(FILE * out);
private:
Expression * condition;
Statement * body;
};
//-----------------------------------------------------------------------------
class WhileStatement : public Statement
{
public:
WhileStatement(Expression * cond, Statement * bdy)
: Statement("while Statement"),
condition(cond),
body(bdy)
{};
 
virtual void Emit(FILE * out);
private:
Expression * condition;
Statement * body;
};
//-----------------------------------------------------------------------------
class ForStatement : public Statement
{
public:
 
ForStatement(ExpressionStatement * f1, ExpressionStatement * f2,
Expression * f3, Statement * bdy)
: Statement("for Statement"),
for_1(f1),
for_2(f2),
for_3(f3),
body(bdy)
{};
 
virtual void Emit(FILE * out);
private:
ExpressionStatement * for_1;
ExpressionStatement * for_2;
Expression * for_3;
Statement * body;
};
//-----------------------------------------------------------------------------
class GotoStatement : public Statement
{
public:
GotoStatement(const char * lab)
: Statement("goto Statement"),
label_name(lab)
{};
 
virtual void Emit(FILE * out);
private:
const char * label_name;
};
//-----------------------------------------------------------------------------
class ReturnStatement : public Statement
{
public:
ReturnStatement(Expression * expr)
: Statement("return Statement"),
retval(expr)
{};
 
virtual void Emit(FILE * out);
private:
Expression * retval;
};
//-----------------------------------------------------------------------------
class ContStatement : public Statement
{
public:
ContStatement(bool do_brk)
: Statement("break/continue Statement"),
do_break(do_brk)
{};
 
virtual void Emit(FILE * out);
private:
bool do_break; // true for break, false for continue
};
//-----------------------------------------------------------------------------
class FunctionDefinition : public Node
{
public:
FunctionDefinition(TypeSpecifier * ds, Declarator * decl,
DeclarationList * dl);
 
virtual void Emit(FILE * out);
 
FunctionDefinition * SetBody(CompoundStatement * bdy)
{ body = bdy; return this; };
private:
TypeName * ret_type;
Declarator * fun_declarator;
DeclarationList * decl_list;
CompoundStatement * body;
};
//-----------------------------------------------------------------------------
 
#endif
/Name.cc
0,0 → 1,213
// Name.cc
 
#include <stdio.h>
#include "Name.hh"
#include "Node.hh"
 
Name * Name::externs = 0;
Name * Name::statics = 0;
Name * Name::enums = 0;
Name * Name::locals = 0;
Name * Name::autos = 0;
 
TypedefName * TypedefName::typedefs = 0;
StructName * StructName::structs = 0;
 
const bool DEBUG = false;
 
//-----------------------------------------------------------------------------
TypeName * TypedefName::Find(const char * na)
{
for (TypedefName * n = typedefs; n; n = n->tail)
{
if (!strcmp(na, n->name)) return n->decl;
}
return 0;
}
//-----------------------------------------------------------------------------
bool TypedefName::IsDefined(const char * na)
{
for (TypedefName * n = typedefs; n; n = n->tail)
{
if (!strcmp(na, n->name)) return true;
}
return false;
}
//-----------------------------------------------------------------------------
void TypedefName::Add(const char * na, TypeName * decl)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to typedefs\n", na);
typedefs = new TypedefName(na, typedefs, decl);
}
//=============================================================================
StructDeclarationList * StructName::Find(const char * na)
{
for (StructName * n = structs; n; n = n->tail)
{
if (!strcmp(na, n->name)) return n->sdlist;
}
return 0;
}
//-----------------------------------------------------------------------------
bool StructName::IsDefined(const char * na)
{
for (StructName * n = structs; n; n = n->tail)
{
if (!strcmp(na, n->name)) return true;
}
return false;
}
//-----------------------------------------------------------------------------
void StructName::Add(const char * na, StructDeclarationList * sdl)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to structs\n", na);
structs = new StructName(na, structs, sdl);
}
//=============================================================================
void Name::RemoveAuto()
{
while (autos)
{
Name * tl = autos->tail;
delete autos;
autos = tl;
}
}
//-----------------------------------------------------------------------------
void Name::AutoToLocal()
{
while (autos)
{
Name * n = autos;
autos = autos->tail;
AutoToLocal();
n->tail = locals;
locals = n;
}
}
//-----------------------------------------------------------------------------
TypeName * Name::FindType(const char * na)
{
Name * np = FindDeclared(na);
 
if (np == 0) return 0;
 
return np->decl;
}
//-----------------------------------------------------------------------------
int Name::FindPos(const char * na)
{
Name * np = FindDeclared(na);
 
if (np == 0) return 1; // +1 indicates error !
 
return np->stack_position;
}
//-----------------------------------------------------------------------------
bool Name::FindEnum(const char * na, int & value)
{
for (Name * n = enums; n; n = n->tail)
{
if (strcmp(na, n->name)) continue;
value = n->stack_position;
return true;
}
 
return false;
}
//-----------------------------------------------------------------------------
Name * Name::FindDeclared(const char * na)
{
for (Name * n = autos; n; n = n->tail)
{
if (!strcmp(na, n->name)) return n;
}
 
for (Name * n = locals; n; n = n->tail)
{
if (!strcmp(na, n->name)) return n;
}
 
for (Name * n = statics; n; n = n->tail)
{
if (!strcmp(na, n->name)) return n;
}
 
for (Name * n = externs; n; n = n->tail)
{
if (!strcmp(na, n->name)) return n;
}
 
return 0;
}
//-----------------------------------------------------------------------------
void Name::Print(FILE * out)
{
fprintf(out, "'%s' %d\n", name, stack_position);
}
//-----------------------------------------------------------------------------
void Name::PrintAll(FILE * out)
{
fprintf(out, "Auto:\n");
for (Name * n = autos; n; n = n->tail) n->Print(out);
 
fprintf(out, "Local:\n");
for (Name * n = locals; n; n = n->tail) n->Print(out);
 
fprintf(out, "Static:\n");
for (Name * n = statics; n; n = n->tail) n->Print(out);
 
fprintf(out, "Extern:\n");
for (Name * n = externs; n; n = n->tail) n->Print(out);
}
//-----------------------------------------------------------------------------
void Name::AddExtern(const char * na, TypeName * decl)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to externs\n", na);
externs = new Name(na, externs, decl, 0);
}
//-----------------------------------------------------------------------------
void Name::AddStatic(const char * na, TypeName * decl)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to statics\n", na);
statics = new Name(na, statics, decl, 0);
}
//-----------------------------------------------------------------------------
void Name::AddLocal(const char * na, TypeName * decl)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to locals\n", na);
locals = new Name(na, locals, decl, 0);
}
//-----------------------------------------------------------------------------
void Name::AddEnum(const char * na, int spos)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to enums\n", na);
enums = new Name(na, enums, 0, spos);
}
//-----------------------------------------------------------------------------
void Name::AddAuto(const char * na, TypeName * decl, int spos)
{
if (DEBUG) fprintf(stderr, "Adding \"%s\" to autos\n", na);
autos = new Name(na, autos, decl, spos);
}
//-----------------------------------------------------------------------------
void Name::SetAutoPos(const char * na, int spos)
{
for (Name * n = autos; n; n = n->tail)
{
if (!strcmp(na, n->name))
{
 
if (DEBUG) fprintf(stderr,
"Setting Stack Position of \"%s\" to %d\n",
na, spos);
assert(n->stack_position == 0);
assert(spos != 0);
assert(spos != 1);
n->stack_position = spos;
return;
}
}
assert(0);
}
//-----------------------------------------------------------------------------
/Backend.hh
0,0 → 1,93
 
#include <stdio.h>
#include <assert.h>
 
#include "Node.hh"
 
enum Size
{
SIZE_CHAR = 1,
SIZE_SHORT = 2,
SIZE_LONG = 4,
 
SIZE_INT = SIZE_SHORT,
SIZE_POINTER = SIZE_INT
};
 
extern FILE * out;
 
class Backend
{
public:
static int check_size(int size, const char * function);
static int check_size(SUW suw, const char * function);
static void file_header();
static void file_footer();
 
static void load_rr_string(int snum, int offset);
static void load_ll_string(int snum, int offset);
static void load_rr_constant(int constant);
static void load_ll_constant(int constant);
 
static void load_rr_var(const char * name, SUW suw);
static void load_ll_var(const char * name, SUW suw);
static void load_rr_var(const char * name, int sp_offset, SUW suw);
static void load_ll_var(const char * name, int sp_offset, SUW suw);
 
static void store_rr_var(const char * name, SUW suw);
static void store_rr_var(const char * name, int sp_offset, SUW suw);
 
static void load_address(const char * name);
static void add_address(const char * name);
static void load_address(const char * name, int sp_offset);
static void assign(int size);
 
static void call(const char * name);
static void call_ptr();
static void ret(int autosize);
 
static void push_rr(SUW suw);
static void pop_rr (SUW suw);
static void pop_ll (SUW suw);
static void pop(int pushed);
static void pop_return(int ret_bytes);
static int push_return(int ret_bytes);
static void push_zero(int bytes);
 
static void move_rr_to_ll();
 
static void compute_unary(int what, const char * pretty);
static void compute_binary(int what, bool uns, const char * pretty);
static void compute_binary(int what, bool uns, const char * pretty,
int value);
static void mult_shift(int value, bool negative);
static void div_shift(int value, bool negative, bool uns);
static void mod_and(int value, bool negative, bool uns);
 
static void compute_binary(int what, bool uns, int value,
const char * pretty);
static void content(SUW suw);
static void scale_rr(int size);
static void unscale_rr(int size, bool uns);
 
static void asmbl(const char * asm_string);
static void asm_adjust(const char * asm_line);
static void label(int lab);
static void label(const char * name);
static void label(const char * name, int loop);
static void label(const char * name, int loop, int value);
static void branch(int lab);
static void branch(const char * name, int loop);
static void branch(const char * name);
static void branch_true(const char * name, int loop, int size);
static void branch_false(const char * name, int lab, int size);
static void branch_case(const char * name, int loop, int size, int value);
static int GetSP() { return stack_pointer; };
static int get_label() { return label_num++; };
static int new_function(const char * fname);
 
private:
static int stack_pointer;
static int label_num;
static int function_num;
};
/ansic.bison
0,0 → 1,694
 
%{
 
#include <stdio.h>
#include "Node.hh"
#include "Name.hh"
 
extern int yylex();
extern int yyparse();
extern int yyerror(const char *);
extern FILE * out;
 
%}
 
%token EOFILE ERROR
%token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF ASM
%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN TYPE_NAME
 
%token TYPEDEF EXTERN STATIC AUTO REGISTER
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
%token STRUCT UNION ENUM ELLIPSIS
 
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
 
%expect 1
 
%start all
 
%union { NumericConstant * _num;
const char *_name;
StringConstant *_string_constant;
BinExprType _bin_expr_type;
UnaExprType _una_expr_type;
Specifier _specifier;
Expression *_expr;
Pointer *_pointer;
IdentifierList *_identifier_list;
Initializer *_initializer;
InitializerList *_initializer_list;
ParameterDeclaration *_parameter_declaration;
ParameterDeclarationList *_parameter_declaration_list;
Declarator *_declarator;
Enumerator *_enumerator;
EnumeratorList *_enumerator_list;
StructDeclarator *_struct_declarator;
StructDeclaratorList *_struct_declarator_list;
StructDeclaration *_struct_declaration;
StructDeclarationList *_struct_declaration_list;
TypeSpecifier *_type_specifier;
InitDeclarator *_init_declarator;
InitDeclaratorList *_init_declarator_list;
Declaration *_declaration;
DeclarationList *_declaration_list;
TypeName *_type_name;
Statement *_statement;
ExpressionStatement *_expression_statement;
CompoundStatement *_compound_statement;
StatementList *_statement_list;
FunctionDefinition *_function_definition;
}
 
%type <_function_definition> function_definition
function_head
%type <_statement_list> statement_list
%type <_statement> statement
labeled_statement
selection_statement
iteration_statement
jump_statement
%type <_expression_statement> expression_statement
%type <_compound_statement> compound_statement
%type <_type_name> type_name
%type <_declaration_list> declaration_list
%type <_declaration> declaration
%type <_init_declarator> init_declarator
%type <_init_declarator_list> init_declarator_list
%type <_type_specifier> struct_or_union_specifier
type_specifier
enum_specifier
declaration_specifiers
type_qualifier_list
specifier_qualifier_list
type_qualifier
%type <_struct_declaration_list> struct_declaration_list
%type <_struct_declaration> struct_declaration
%type <_struct_declarator_list> struct_declarator_list
%type <_struct_declarator> struct_declarator
%type <_enumerator> enumerator
%type <_enumerator_list> enumerator_list
%type <_declarator> declarator
direct_declarator
abstract_declarator
direct_abstract_declarator
%type <_parameter_declaration> parameter_declaration
%type <_parameter_declaration_list> parameter_list
%type <_initializer> initializer
%type <_initializer_list> initializer_list
%type <_identifier_list> identifier_list
%type <_pointer> pointer
%type <_specifier> struct_or_union
%type <_una_expr_type> unary_operator
%type <_bin_expr_type> assignment_operator
%type <_name> IDENTIFIER TYPE_NAME
%type <_string_constant> STRING_LITERAL
string_sequence
%type <_num> CONSTANT
%type <_expr> expression
primary_expression
postfix_expression
argument_expression_list
unary_expression
cast_expression
multiplicative_expression
additive_expression
shift_expression
relational_expression
equality_expression
and_expression
exclusive_or_expression
inclusive_or_expression
logical_and_expression
logical_or_expression
conditional_expression
assignment_expression
constant_expression
 
%%
 
all : translation_unit EOFILE
{ StringConstant::EmitAll(out); return 0; }
;
 
primary_expression
: IDENTIFIER { $$ = IdentifierExpression::New($1); }
| CONSTANT { $$ = new NumericExpression($1); }
| string_sequence { $$ = new StringExpression($1); }
| '(' expression ')' { $$ = $2; }
| ASM '(' string_sequence ')' { $$ = new AsmExpression($3); }
;
 
string_sequence
: STRING_LITERAL { $$ = $1; }
| string_sequence STRING_LITERAL { $$ = *$1 & $2; }
;
 
postfix_expression
: primary_expression
{ $$ = $1; }
| postfix_expression '[' expression ']'
{ $$ = BinaryExpression::New(ET_ELEMENT, $1, $3); }
| postfix_expression '(' ')'
{ $$ = BinaryExpression::New(ET_FUNCALL, $1, 0); }
| postfix_expression '(' argument_expression_list ')'
{ $$ = BinaryExpression::New(ET_FUNCALL, $1, $3); }
| postfix_expression '.' IDENTIFIER
{ $$ = new MemberExpression(false, $1, $3); }
| postfix_expression PTR_OP IDENTIFIER
{ $$ = new MemberExpression(true, $1, $3); }
| postfix_expression INC_OP
{ $$ = UnaryExpression::New(ET_POSTINC, $1); }
| postfix_expression DEC_OP
{ $$ = UnaryExpression::New(ET_POSTDEC, $1); }
;
 
argument_expression_list
: assignment_expression
{ $$ = $1; }
| argument_expression_list ',' assignment_expression
{ $$ = new ArgListExpression($1, $3); }
;
 
unary_expression
: postfix_expression
{ $$ = $1; }
| INC_OP unary_expression
{ $$ = UnaryExpression::New(ET_PREINC, $2); }
| DEC_OP unary_expression
{ $$ = UnaryExpression::New(ET_PREDEC, $2); }
| unary_operator cast_expression
{ $$ = UnaryExpression::New($1, $2); }
| SIZEOF unary_expression
{ $$ = new NumericExpression($2); }
| SIZEOF '(' type_name ')'
{ $$ = new NumericExpression($3); }
;
 
unary_operator
: '&' { $$ = ET_ADDRESS; }
| '*' { $$ = ET_CONTENT; }
| '+' { $$ = ET_CONJUGATE; }
| '-' { $$ = ET_NEGATE; }
| '~' { $$ = ET_COMPLEMENT; }
| '!' { $$ = ET_LOG_NOT; }
;
 
cast_expression
: unary_expression
{ $$ = $1; }
| '(' type_name ')' cast_expression
{ $$ = new UnaryExpression($2, $4); }
;
 
multiplicative_expression
: cast_expression
{ $$ = $1; }
| multiplicative_expression '*' cast_expression
{ $$ = BinaryExpression::New(ET_MULT, $1, $3); }
| multiplicative_expression '/' cast_expression
{ $$ = BinaryExpression::New(ET_DIV, $1, $3); }
| multiplicative_expression '%' cast_expression
{ $$ = BinaryExpression::New(ET_MOD, $1, $3); }
;
 
additive_expression
: multiplicative_expression
{ $$ = $1; }
| additive_expression '+' multiplicative_expression
{ $$ = AdditionExpression::New($1, $3); }
| additive_expression '-' multiplicative_expression
{ $$ = SubtractionExpression::New($1, $3); }
;
 
shift_expression
: additive_expression
{ $$ = $1; }
| shift_expression LEFT_OP additive_expression
{ $$ = BinaryExpression::New(ET_LEFT, $1, $3); }
| shift_expression RIGHT_OP additive_expression
{ $$ = BinaryExpression::New(ET_RIGHT, $1, $3); }
;
 
relational_expression
: shift_expression
{ $$ = $1; }
| relational_expression '<' shift_expression
{ $$ = BinaryExpression::New(ET_LESS, $1, $3); }
| relational_expression '>' shift_expression
{ $$ = BinaryExpression::New(ET_GREATER, $1, $3); }
| relational_expression LE_OP shift_expression
{ $$ = BinaryExpression::New(ET_LESS_EQUAL, $1, $3); }
| relational_expression GE_OP shift_expression
{ $$ = BinaryExpression::New(ET_GREATER_EQUAL, $1, $3); }
;
 
equality_expression
: relational_expression
{ $$ = $1; }
| equality_expression EQ_OP relational_expression
{ $$ = BinaryExpression::New(ET_EQUAL, $1, $3); }
| equality_expression NE_OP relational_expression
{ $$ = BinaryExpression::New(ET_NOT_EQUAL, $1, $3); }
;
 
and_expression
: equality_expression
{ $$ = $1; }
| and_expression '&' equality_expression
{ $$ = BinaryExpression::New(ET_BIT_AND, $1, $3); }
;
 
exclusive_or_expression
: and_expression
{ $$ = $1; }
| exclusive_or_expression '^' and_expression
{ $$ = BinaryExpression::New(ET_BIT_XOR, $1, $3); }
;
 
inclusive_or_expression
: exclusive_or_expression
{ $$ = $1; }
| inclusive_or_expression '|' exclusive_or_expression
{ $$ = BinaryExpression::New(ET_BIT_OR, $1, $3); }
;
 
logical_and_expression
: inclusive_or_expression
{ $$ = $1; }
| logical_and_expression AND_OP inclusive_or_expression
{ $$ = BinaryExpression::New(ET_LOG_AND, $1, $3); }
;
 
logical_or_expression
: logical_and_expression
{ $$ = $1; }
| logical_or_expression OR_OP logical_and_expression
{ $$ = BinaryExpression::New(ET_LOG_OR, $1, $3); }
;
 
conditional_expression
: logical_or_expression
{ $$ = $1; }
| logical_or_expression '?' expression ':' conditional_expression
{ $$ = new CondExpression($1, $3, $5); }
;
 
assignment_expression
: conditional_expression
{ $$ = $1; }
| unary_expression assignment_operator assignment_expression
{ $$ = BinaryExpression::New($2, $1, $3); }
;
 
assignment_operator
: '=' { $$ = ET_ASSIGN; }
| MUL_ASSIGN { $$ = ET_MULT_ASSIGN; }
| DIV_ASSIGN { $$ = ET_DIV_ASSIGN; }
| MOD_ASSIGN { $$ = ET_MOD_ASSIGN; }
| ADD_ASSIGN { $$ = ET_ADD_ASSIGN; }
| SUB_ASSIGN { $$ = ET_SUB_ASSIGN; }
| LEFT_ASSIGN { $$ = ET_LEFT_ASSIGN; }
| RIGHT_ASSIGN { $$ = ET_RIGHT_ASSIGN; }
| AND_ASSIGN { $$ = ET_AND_ASSIGN; }
| XOR_ASSIGN { $$ = ET_XOR_ASSIGN; }
| OR_ASSIGN { $$ = ET_OR_ASSIGN; }
;
 
expression
: assignment_expression
{ $$ = $1; }
| expression ',' assignment_expression
{ $$ = BinaryExpression::New(ET_LIST, $1, $3); }
;
 
constant_expression
: conditional_expression
{ $$ = $1; }
;
 
declaration
: declaration_specifiers ';'
{ $$ = new Declaration($1, 0); }
| declaration_specifiers init_declarator_list ';'
{ $$ = new Declaration($1, $2); }
;
 
declaration_specifiers
: type_specifier { $$ = $1; }
| type_qualifier { $$ = $1; }
| type_specifier declaration_specifiers { $$ = *$2 + *$1; }
| type_qualifier declaration_specifiers { $$ = *$2 + *$1; }
;
 
init_declarator_list
: init_declarator
{ $$ = new InitDeclaratorList($1, 0); }
| init_declarator ',' init_declarator_list
{ $$ = new InitDeclaratorList($1, $3); }
;
 
init_declarator
: declarator
{ $$ = new InitDeclarator($1, 0); }
| declarator '=' initializer
{ $$ = new InitDeclarator($1, $3); }
;
 
type_specifier
// storage class
: TYPEDEF { $$ = new TypeSpecifier(SC_TYPEDEF); }
| EXTERN { $$ = new TypeSpecifier(SC_EXTERN); }
| STATIC { $$ = new TypeSpecifier(SC_STATIC); }
| AUTO { $$ = new TypeSpecifier(SC_AUTO); }
| REGISTER { $$ = new TypeSpecifier(SC_REGISTER); }
// type
| VOID { $$ = new TypeSpecifier(TS_VOID); }
| CHAR { $$ = new TypeSpecifier(TS_CHAR); }
| SHORT { $$ = new TypeSpecifier(TS_SHORT); }
| INT { $$ = new TypeSpecifier(TS_INT); }
| LONG { $$ = new TypeSpecifier(TS_LONG); }
| FLOAT { $$ = new TypeSpecifier(TS_FLOAT); }
| DOUBLE { $$ = new TypeSpecifier(TS_DOUBLE); }
| SIGNED { $$ = new TypeSpecifier(TS_SIGNED); }
| UNSIGNED { $$ = new TypeSpecifier(TS_UNSIGNED); }
| struct_or_union_specifier { $$ = $1; }
| enum_specifier { $$ = $1; }
| TYPE_NAME { $$ = new TypeSpecifier(TS_TYPE_NAME, $1, 0); }
;
 
struct_or_union_specifier
: struct_or_union IDENTIFIER '{' struct_declaration_list '}'
{ $$ = new TypeSpecifier($1, $2, $4); }
| struct_or_union '{' struct_declaration_list '}'
{ $$ = new TypeSpecifier($1, 0, $3); }
| struct_or_union IDENTIFIER
{ $$ = new TypeSpecifier($1, $2, 0); }
;
 
struct_or_union
: STRUCT { $$ = TS_STRUCT; }
| UNION { $$ = TS_UNION; }
;
 
struct_declaration_list
: struct_declaration
{ $$ = new StructDeclarationList($1, 0); }
| struct_declaration struct_declaration_list
{ $$ = new StructDeclarationList($1, $2); }
;
 
struct_declaration
: specifier_qualifier_list struct_declarator_list ';'
{ $$ = new StructDeclaration($1, $2); }
;
 
specifier_qualifier_list
: type_specifier { $$ = $1; }
| type_qualifier { $$ = $1; }
| type_specifier specifier_qualifier_list { $$=*$1 + *$2; }
| type_qualifier specifier_qualifier_list { $$=*$1 + *$2; }
;
 
struct_declarator_list
: struct_declarator
{ $$ = new StructDeclaratorList($1, 0); }
| struct_declarator ',' struct_declarator_list
{ $$ = new StructDeclaratorList($1, $3); }
;
 
struct_declarator
: declarator
{ $$ = new StructDeclarator($1, 0); }
| ':' constant_expression
{ $$ = new StructDeclarator( 0, $2); }
| declarator ':' constant_expression
{ $$ = new StructDeclarator($1, $3); }
;
 
enum_specifier
: ENUM '{' enumerator_list '}'
{ $$ = new TypeSpecifier( 0, $3); }
| ENUM IDENTIFIER '{' enumerator_list '}'
{ $$ = new TypeSpecifier($2, $4); }
| ENUM IDENTIFIER
{ $$ = new TypeSpecifier(TS_ENUM); }
;
 
enumerator_list
: enumerator
{ $$ = new EnumeratorList($1, 0); }
| enumerator ',' enumerator_list
{ $$ = new EnumeratorList($1, $3); }
;
 
enumerator
: IDENTIFIER { $$ = new Enumerator($1, 0); }
| IDENTIFIER '=' constant_expression
{ $$ = new Enumerator($1, $3); }
;
 
type_qualifier
: CONST { $$ = new TypeSpecifier(TQ_CONST); }
| VOLATILE { $$ = new TypeSpecifier(TQ_VOLATILE); }
;
 
declarator
: pointer direct_declarator
{ $$ = new Declarator(new DeclItem($1), $2->Reverse()); }
| direct_declarator
{ $$ = $1->Reverse(); }
;
 
direct_declarator
: IDENTIFIER
{ $$ = new Declarator(new DeclItem($1), 0); }
| '(' declarator ')'
{ $$ = new Declarator(new DeclItem($2), 0); }
| direct_declarator '[' constant_expression ']'
{ $$ = new Declarator(new DeclItem($3), $1); }
| direct_declarator '[' ']'
{ $$ = new Declarator(new DeclItem(DECL_ARRAY), $1); }
| direct_declarator '(' parameter_list ')'
{ $$ = new Declarator(new DeclItem($3), $1); }
| direct_declarator '(' identifier_list ')'
{ $$ = new Declarator(new DeclItem($3), $1); }
| direct_declarator '(' ')'
{ $$ = new Declarator(new DeclItem(DECL_FUN), $1); }
;
 
pointer
: '*'
{ $$ = new Pointer(new Ptr(0), 0); }
| '*' type_qualifier_list
{ $$ = new Pointer(new Ptr($2), 0); }
| '*' pointer
{ $$ = new Pointer(new Ptr(0), $2); }
| '*' type_qualifier_list pointer
{ $$ = new Pointer(new Ptr($2), $3); }
;
 
type_qualifier_list
: type_qualifier { $$ = $1 }
| type_qualifier type_qualifier_list { $$ = *$1 + *$2; }
;
 
parameter_list
: parameter_declaration
{ $$ = new ParameterDeclarationList($1, 0); }
| ELLIPSIS
{ $$ = new ParameterDeclarationList( 0, 0); }
| parameter_declaration ',' parameter_list
{
if ($3->Head()) $$ = new ParameterDeclarationList($1, $3);
else $$ = $3->SetHead($1->SetEllipsis());
}
;
 
parameter_declaration
: declaration_specifiers declarator
{ $$ = new ParameterDeclaration($1, $2); }
| declaration_specifiers abstract_declarator
{ $$ = new ParameterDeclaration($1, $2); }
| declaration_specifiers
{ $$ = new ParameterDeclaration($1, 0); }
;
 
identifier_list
: IDENTIFIER
{ $$ = new IdentifierList(new Identifier($1), 0); }
| IDENTIFIER ',' identifier_list
{ $$ = new IdentifierList(new Identifier($1), $3); }
;
 
type_name
: specifier_qualifier_list
{ assert($1); $$ = new TypeName($1, 0); }
| specifier_qualifier_list abstract_declarator
{ assert($1); $$ = new TypeName($1, $2); }
;
 
abstract_declarator
: pointer
{ $$ = new Declarator(new DeclItem($1), 0); }
| direct_abstract_declarator
{ $$ = $1->Reverse(); }
| pointer direct_abstract_declarator
{ $$ = new Declarator(new DeclItem($1), $2->Reverse()); }
;
 
direct_abstract_declarator
: '(' abstract_declarator ')'
{ $$ = new Declarator(new DeclItem($2), 0); }
| '[' ']'
{ $$ = new Declarator(new DeclItem(DECL_ARRAY), 0); }
| '[' constant_expression ']'
{ $$ = new Declarator(new DeclItem($2), 0); }
| '(' ')'
{ $$ = new Declarator(new DeclItem(DECL_FUN), 0); }
| '(' parameter_list ')'
{ $$ = new Declarator(new DeclItem($2), 0); }
| direct_abstract_declarator '[' ']'
{ $$ = new Declarator(new DeclItem(DECL_ARRAY), $1); }
| direct_abstract_declarator '[' constant_expression ']'
{ $$ = new Declarator(new DeclItem($3), $1); }
| direct_abstract_declarator '(' ')'
{ $$ = new Declarator(new DeclItem(DECL_FUN), $1); }
| direct_abstract_declarator '(' parameter_list ')'
{ $$ = new Declarator(new DeclItem($3), $1); }
;
 
initializer
: assignment_expression
{ $$ = new Initializer($1); }
| '{' initializer_list '}'
{ $$ = new Initializer($2->Reverse()); }
| '{' initializer_list ',' '}'
{ $$ = new Initializer($2->Reverse()); }
;
 
initializer_list
: initializer
{ $$ = new InitializerList($1, 0); }
| initializer_list ',' initializer
{ $$ = new InitializerList($3, $1); }
;
 
statement
: labeled_statement { $$ = $1; }
| compound_statement { $$ = $1; }
| expression_statement { $$ = $1; }
| selection_statement { $$ = $1; }
| iteration_statement { $$ = $1; }
| jump_statement { $$ = $1; }
;
 
labeled_statement
: IDENTIFIER ':' statement
{ $$ = new LabelStatement($1, $3); }
| CASE constant_expression ':' statement
{ $$ = new CaseStatement($2, $4); }
| DEFAULT ':' statement
{ $$ = new CaseStatement(0, $3); }
;
 
compound_statement
: '{' '}'
{ $$ = new CompoundStatement( 0, 0); }
| '{' statement_list '}'
{ $$ = new CompoundStatement( 0, $2); }
| '{' declaration_list '}'
{ $$ = new CompoundStatement($2, 0); }
| '{' declaration_list statement_list '}'
{ $$ = new CompoundStatement($2, $3); }
;
 
declaration_list
: declaration
{ $$ = new DeclarationList($1, 0); }
| declaration declaration_list
{ $$ = new DeclarationList($1, $2); }
;
 
statement_list
: statement
{ $$ = new StatementList($1, 0); }
| statement statement_list
{ $$ = new StatementList($1, $2); }
;
 
expression_statement
: ';' { $$ = new ExpressionStatement(0); }
| expression ';' { $$ = new ExpressionStatement($1); }
| error ';' { $$ = new ExpressionStatement(0);
Node::Error(); }
;
 
selection_statement
: IF '(' expression ')' statement
{ $$ = new IfElseStatement($3, $5, 0); }
| IF '(' expression ')' statement ELSE statement
{ $$ = new IfElseStatement($3, $5, $7); }
| SWITCH '(' expression ')' compound_statement
{ $$ = new SwitchStatement($3, $5); }
;
 
iteration_statement
: WHILE '(' expression ')' statement
{ $$ = new WhileStatement($3, $5); }
| DO statement WHILE '(' expression ')' ';'
{ $$ = new DoWhileStatement($2, $5); }
| FOR '(' expression_statement expression_statement ')' statement
{ $$ = new ForStatement($3, $4, 0, $6); }
| FOR '(' expression_statement expression_statement
expression ')' statement
{ $$ = new ForStatement($3, $4, $5, $7); }
;
 
jump_statement
: GOTO IDENTIFIER ';' { $$ = new GotoStatement($2); }
| CONTINUE ';' { $$ = new ContStatement(false); }
| BREAK ';' { $$ = new ContStatement(true); }
| RETURN ';' { $$ = new ReturnStatement(0); }
| RETURN expression ';' { $$ = new ReturnStatement($2); }
;
 
translation_unit
: external_declaration { }
| external_declaration translation_unit { }
;
 
external_declaration
: function_definition
{ $1->Emit(out);
fprintf(out,
";;; ------------------------------------;\n"); }
| declaration
{ if ($1) $1->Emit(out);
fprintf(out,
";;; ------------------------------------;\n"); }
| error
{ Node::Error();
fprintf(out,
";;; SYNTAX ERROR\n"
";;; ------------------------------------;\n"); }
;
 
function_head
: declaration_specifiers declarator declaration_list
{ $$ = new FunctionDefinition($1, $2, $3); }
| declaration_specifiers declarator
{ $$ = new FunctionDefinition($1, $2, 0); }
| declarator declaration_list
{ $$ = new FunctionDefinition( 0, $1, $2); }
| declarator
{ $$ = new FunctionDefinition( 0, $1, 0); }
;
 
function_definition
: function_head compound_statement
{ $$ = $1->SetBody($2); }
;
%%
/Statement.cc
0,0 → 1,384
// Statement.cc
 
#include <stdio.h>
#include <assert.h>
#include "Node.hh"
#include "Name.hh"
#include "Backend.hh"
 
class LoopStack
{
public:
LoopStack(int num, LoopStack * prev)
: number(num),
previous(prev)
{};
 
static int Push(LoopStack * & stack);
static void Pop(LoopStack * & stack, int val);
static int Get(LoopStack * & stack)
{ assert(stack); return stack->number; };
 
private:
int number;
LoopStack * previous;
 
static int next_number;
};
 
int LoopStack::next_number = 1;
 
LoopStack * loop_stack = 0;
LoopStack * break_stack = 0;
 
//-----------------------------------------------------------------------------
int LoopStack::Push(LoopStack * & stack)
{
stack = new LoopStack(next_number++, stack);
return stack->number;
}
//-----------------------------------------------------------------------------
void LoopStack::Pop(LoopStack * & stack, int val)
{
assert(stack);
assert(val == stack->number);
 
LoopStack * del = stack;
stack = stack->previous;
delete del;
}
//=============================================================================
void ExpressionStatement::Emit(FILE * out)
{
EmitStart(out);
if (expression) expression->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void SwitchStatement::Emit(FILE * out)
{
const int brk = LoopStack::Push(break_stack);
 
EmitStart(out);
 
assert(condition);
condition->Emit(out);
Backend::move_rr_to_ll();
 
assert(case_stat);
case_stat->EmitCaseJumps(out, condition->GetSize());
 
EmitEnd(out);
 
LoopStack::Pop(break_stack, brk);
}
//-----------------------------------------------------------------------------
void IfElseStatement::Emit(FILE * out)
{
const int loop = LoopStack::Push(loop_stack); // just get a number
LoopStack::Pop(loop_stack, loop);
 
EmitStart(out);
assert(condition);
condition->Emit(out);
 
const int size = condition->GetSize();
 
if (if_stat)
{
if (else_stat) // if and else
{
Backend::branch_false("else", loop, size);
if_stat->Emit(out);
Backend::branch("endif", loop);
Backend::label("else", loop);
else_stat->Emit(out);
Backend::label("endif", loop);
}
else // if only
{
Backend::branch_false("endif", loop, size);
if_stat->Emit(out);
Backend::label("endif", loop);
}
}
else
{
if (else_stat) // else only
{
Backend::branch_true("endif", loop, size);
else_stat->Emit(out);
Backend::label("endif", loop);
}
else // nothing
{
}
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void DoWhileStatement::Emit(FILE * out)
{
const int loop = LoopStack::Push(loop_stack);
const int brk = LoopStack::Push(break_stack);
 
EmitStart(out);
 
assert(condition);
assert(body);
 
const int size = condition->GetSize();
 
Backend::label("loop", loop);
body->Emit(out);
 
Backend::label("cont", loop);
condition->Emit(out);
Backend::branch_true("loop", loop, size);
 
Backend::label("brk", brk);
 
EmitEnd(out);
 
LoopStack::Pop(break_stack, brk);
LoopStack::Pop(loop_stack, loop);
}
//-----------------------------------------------------------------------------
void WhileStatement::Emit(FILE * out)
{
const int loop = LoopStack::Push(loop_stack);
const int brk = LoopStack::Push(break_stack);
 
EmitStart(out);
 
assert(condition);
assert(body);
 
const int size = condition->GetSize();
 
if (body->NotEmpty()) Backend::branch("cont", loop);
 
Backend::label("loop", loop);
body->Emit(out);
 
Backend::label("cont", loop);
condition->Emit(out);
Backend::branch_true("loop", loop, size);
 
Backend::label("brk", brk);
 
EmitEnd(out);
 
LoopStack::Pop(break_stack, brk);
LoopStack::Pop(loop_stack, loop);
}
//-----------------------------------------------------------------------------
void ForStatement::Emit(FILE * out)
{
const int loop = LoopStack::Push(loop_stack);
const int brk = LoopStack::Push(break_stack);
 
EmitStart(out);
 
assert(for_1);
assert(for_2);
assert(body);
 
Expression * cond = for_2->GetExpression();
 
int size = 0;
if (cond) size = cond->GetSize();
 
for_1->Emit(out);
 
if (cond) Backend::branch("tst", loop);
 
Backend::label("loop", loop);
body->Emit(out);
 
Backend::label("cont", loop);
if (for_3) for_3->Emit(out);
 
 
if (cond)
{
Backend::label("tst", loop);
cond->Emit(out);
Backend::branch_true("loop", loop, size);
}
else
{
Backend::branch("loop", loop);
}
 
Backend::label("brk", brk);
 
EmitEnd(out);
 
LoopStack::Pop(break_stack, brk);
LoopStack::Pop(loop_stack, loop);
}
//-----------------------------------------------------------------------------
void LabelStatement::Emit(FILE * out)
{
EmitStart(out);
 
assert(label_name);
assert(statement);
 
Backend::label(label_name);
statement->Emit(out);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void GotoStatement::Emit(FILE * out)
{
EmitStart(out);
 
assert(label_name);
 
Backend::branch(label_name);
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void ReturnStatement::Emit(FILE * out)
{
EmitStart(out);
 
if (retval) retval->Emit(out);
 
Backend::branch("return");
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void ContStatement::Emit(FILE * out)
{
EmitStart(out);
 
if (do_break)
{
Backend::branch("brk", LoopStack::Get(break_stack));
}
else
{
Backend::branch("cont", LoopStack::Get(loop_stack));
}
 
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void CompoundStatement::Emit(FILE * out)
{
EmitStart(out);
if (stat_list) stat_list->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
int CompoundStatement::EmitAutovars(FILE * out)
{
int ret = 0;
 
for (DeclarationList * d = decl_list; d; d = d->Tail())
{
Declaration * di = d->Head();
assert(di);
int len = di->EmitAutovars(out);
assert(len > 0);
ret += len;
}
 
return ret;
}
//-----------------------------------------------------------------------------
void CompoundStatement::EmitCaseJumps(FILE * out, int size)
{
const int brk = LoopStack::Get(break_stack);
 
bool has_default = false;
 
for (StatementList * sl = stat_list; sl; sl = sl->Tail())
{
Statement * s = sl->Head();
assert(s);
s->EmitCaseJump(out, false, brk, size);
}
 
for (StatementList * sl = stat_list; sl; sl = sl->Tail())
{
Statement * s = sl->Head();
assert(s);
if (s->EmitCaseJump(out, true, brk, size)) has_default = true;
}
 
if (!has_default)
{
Backend::branch("brk", brk);
}
 
Emit(out);
 
Backend::label("brk", brk);
}
//-----------------------------------------------------------------------------
void CaseStatement::Emit(FILE * out)
{
const int brk = LoopStack::Get(break_stack);
 
EmitStart(out);
if (case_value)
{
if (case_value->IsConstant())
{
const int value = case_value->GetConstantNumericValue();
Backend::label("case", brk, value);
}
else
{
fprintf(stderr, "Case value not constant\r\n");
semantic_errors++;
}
}
else
{
Backend::label("deflt", brk);
}
 
if (statement) statement->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
//
// return true iff this is a default clause
//
bool CaseStatement::EmitCaseJump(FILE * out, bool def, int loop, int size)
{
bool ret = false;
 
if (def) // default branch
{
if (!case_value) { Backend::branch("deflt", loop); ret = true; }
}
else // case branch
{
if (case_value)
{
if (!case_value->IsConstant())
{
fprintf(stderr, "case value not constant\r\n");
semantic_errors++;
return false;
}
 
const int value = case_value->GetConstantNumericValue();
Backend::branch_case("case", loop, size, value);
}
}
 
if (statement) ret = ret || statement->EmitCaseJump(out, def, loop, size);
return ret;
}
//-----------------------------------------------------------------------------
/List.hh
0,0 → 1,107
// List.hh
#ifndef __LIST_HH_DEFINED__
#define __LIST_HH_DEFINED__
 
//-----------------------------------------------------------------------------
class Node
{
public:
Node(const char * ntype);
 
virtual void Emit(FILE * out);
void EmitStart(FILE * out);
void EmitEnd(FILE * out);
 
static void EmitIndent(FILE * out);
static int GetSemanticErrors() { return semantic_errors; };
static void Error() { ++semantic_errors; };
const char * GetNodeType() const { return node_type; };
 
protected:
const char * node_type;
 
static int indent;
static int semantic_errors;
};
//-----------------------------------------------------------------------------
template <class C>
class List : public Node
{
public:
List(C * h, List<C> * t)
: Node(list_name(h, t)),
head(h), tail(t) {};
 
virtual void Emit(FILE * out);
 
C * Head() { return head; };
List<C> * Tail() { return tail; };
void ForceEnd() { tail = 0; };
 
List<C> * Reverse()
{
List<C> * ret = 0;
for (List<C> * l = this; l; l = l->tail)
{
ret = new List<C>(l->head, ret);
}
return ret;
};
 
static int Length(const List<C> * l)
{
int ret = 0;
for (; l; l = l->tail) ret++;
return ret;
};
 
void List<C>::EmitList(FILE * out)
{
EmitStart(out);
for (List<C> * l = this; l; l = l->tail)
if (l->Head()) l->Head()->Emit(out);
EmitEnd(out);
};
 
List<C> * List<C>::SetHead(C * hd)
{
assert(head == 0);
head = hd;
return this;
};
 
static const char * list_name(C * h, List<C> * t)
{
if (h == 0)
{
for (; t; t = t->tail) if (h = t->head) break;
}
 
if (h == 0) return "List";
char * cp = new char[strlen(h->GetNodeType()) + 10];
sprintf(cp, "List<%s>", h->GetNodeType());
return cp;
};
 
private:
C * head;
List<C> * tail;
};
//-----------------------------------------------------------------------------
 
class DeclItem; typedef List<DeclItem> Declarator;
class Initializer; typedef List<Initializer> InitializerList;
class Enumerator; typedef List<Enumerator> EnumeratorList;
class InitDeclarator; typedef List<InitDeclarator> InitDeclaratorList;
class Ptr; typedef List<Ptr> Pointer;
class Identifier; typedef List<Identifier> IdentifierList;
class Declaration; typedef List<Declaration> DeclarationList;
class Statement; typedef List<Statement> StatementList;
class TypeSpecifier; typedef List<TypeSpecifier> TypeSpecifierList;
class ParameterDeclaration; typedef List<ParameterDeclaration>
ParameterDeclarationList;
class StructDeclarator; typedef List<StructDeclarator>
StructDeclaratorList;
class StructDeclaration; typedef List<StructDeclaration>
StructDeclarationList;
#endif
/Node.cc
0,0 → 1,1696
 
#include <stdio.h>
#include <assert.h>
#include "Node.hh"
#include "Name.hh"
#include "Backend.hh"
 
int Node::indent = 0;
int Node::semantic_errors = 0;
 
int Enumerator::current = 0;
int TypeSpecifier::anonymous_number = 1;
 
extern FILE * out;
 
//-----------------------------------------------------------------------------
void NumericConstant::EmitValue_RR(FILE * out)
{
Backend::load_rr_constant(value);
}
//-----------------------------------------------------------------------------
void NumericConstant::EmitValue_LL(FILE * out)
{
Backend::load_ll_constant(value);
}
//-----------------------------------------------------------------------------
void StringConstant::EmitValue_RR(FILE * out)
{
Backend::load_rr_string(string_number, 0);
}
//-----------------------------------------------------------------------------
void StringConstant::EmitValue_LL(FILE * out)
{
Backend::load_ll_string(string_number, 0);
}
//-----------------------------------------------------------------------------
Node::Node(const char * ntype)
: node_type(ntype)
{
// printf("Creating %s\n", node_type);
}
//-----------------------------------------------------------------------------
void Node::Emit(FILE * out)
{
EmitIndent(out);
fprintf(out, "MISSING : %s\n", node_type);
fprintf(stderr, "\n\nMISSING : %s::Emit()\n\n", node_type);
}
//-----------------------------------------------------------------------------
void Node::EmitIndent(FILE * out)
{
fprintf(out, ";;; ");
for (int i = 0; i < indent; i++) fprintf(out, " ");
}
//-----------------------------------------------------------------------------
void Node::EmitStart(FILE * out)
{
EmitIndent(out);
fprintf(out, "{ %d %s\n", indent, node_type);
indent++;
}
//-----------------------------------------------------------------------------
void Node::EmitEnd(FILE * out)
{
indent--;
EmitIndent(out);
fprintf(out, "} %d %s\n", indent, node_type);
}
//-----------------------------------------------------------------------------
void StatementList ::Emit(FILE * out) { EmitList(out); }
void DeclarationList ::Emit(FILE * out) { EmitList(out); }
void InitializerList ::Emit(FILE * out) { EmitList(out); }
void ParameterDeclarationList::Emit(FILE * out) { EmitList(out); }
void IdentifierList ::Emit(FILE * out) { EmitList(out); }
void StructDeclaratorList ::Emit(FILE * out) { assert(0); }
void StructDeclarationList ::Emit(FILE * out) { assert(0); }
void InitDeclaratorList ::Emit(FILE * out) { EmitList(out); }
void TypeSpecifierList ::Emit(FILE * out) { EmitList(out); }
void Declarator ::Emit(FILE * out) { EmitList(out); }
void Pointer ::Emit(FILE * out) { EmitList(out); }
//-----------------------------------------------------------------------------
void StructDeclarator::Emit(FILE * out)
{
assert(declarator);
EmitStart(out);
declarator->Emit(out);
if (expression)
{
EmitIndent(out);
fprintf(out, " : bitfield\n");
}
 
EmitIndent(out);
fprintf(out, " at position %d\n", position);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
int StructDeclarator::EmitMember(FILE * out, const char * struct_name,
TypeSpecifier * tspec, int pos, bool is_union)
{
position = pos;
if (is_union) assert(position == 0);
 
if (0)
{
const char * member_name = GetDeclaredName(declarator);
 
assert(struct_name);
if (member_name == 0) member_name = "anonymous member";
 
fprintf(stderr, "%s->%s at position %d\n",
struct_name, member_name, position);
}
 
return tspec->GetSize(declarator);
}
//-----------------------------------------------------------------------------
void EnumeratorList::Emit(FILE * out)
{
Enumerator::current = 0;
 
for (EnumeratorList * el = this; el; el = el->tail)
el->head->Emit(out);
}
//-----------------------------------------------------------------------------
void Enumerator::Emit(FILE * out)
{
assert(name);
 
int val = current++;
if (value)
{
if (!value->IsNumericConstant())
{
fprintf(stderr, "enum value for %s is not constant\n", name);
semantic_errors++;
}
else
{
val = value->GetConstantNumericValue();
current = val + 1;
}
}
Name::AddEnum(name, val);
}
//-----------------------------------------------------------------------------
ParameterDeclaration::ParameterDeclaration(TypeSpecifier * ds,
Declarator * decl)
: Node("ParameterDeclaration"),
isEllipsis(false)
{
type = new TypeName(ds, decl);
 
const char * pname = type->GetDeclaredName();
 
if (pname) Name::AddAuto(pname, type);
}
//-----------------------------------------------------------------------------
void ParameterDeclaration::Emit(FILE * out)
{
EmitStart(out);
EmitIndent(out);
fprintf(out, "isEllipsis = ");
if (isEllipsis) fprintf(out, "true\r\n");
else fprintf(out, "false\r\n");
type->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
int ParameterDeclaration::AllocateParameters(int offset)
{
const int size = type->GetSize();
const char * pname = GetDeclaredName(0);
 
if (pname) Name::SetAutoPos(pname, offset);
 
return size;
}
//-----------------------------------------------------------------------------
const char * ParameterDeclaration::GetDeclaredName(int skip)
{
for (Declarator * d = type->GetDeclarator(); d; d = d->Tail())
{
const char * n = d->Head()->GetName();
if (n == 0) continue;
if (skip == 0) return n;
skip--;
}
return 0;
}
//-----------------------------------------------------------------------------
FunctionDefinition::FunctionDefinition(TypeSpecifier * ds,
Declarator * decl,
DeclarationList * dl)
: Node("FunctionDefinition"),
fun_declarator(decl),
decl_list(dl),
body(0)
{
// these are always present...
//
assert(decl);
 
// no type means int
//
if (ds == 0) ds = new TypeSpecifier(TS_INT);
 
Declarator * ret_decl = 0;
 
// copy decl to ret_decl up to FUN_DECL
//
for (Declarator * d = decl; d; d = d->Tail())
{
DeclItem * di = d->Head();
assert(di);
if (di->GetWhat() == DECL_FUN) break;
ret_decl = new Declarator(di, ret_decl);
}
 
const char * fun_name = ::GetDeclaredName(fun_declarator);
assert(fun_name);
 
ret_type = new TypeName(ds, ret_decl);
 
TypeName * fun_type = new TypeName(ds, fun_declarator);
Name::AddLocal(fun_name, fun_type);
}
//-----------------------------------------------------------------------------
void FunctionDefinition::Emit(FILE * out)
{
EmitStart(out);
 
assert(ret_type);
ret_type->Emit(out);
 
assert(fun_declarator);
fun_declarator->Emit(out);
 
if (decl_list) decl_list->Emit(out);
 
assert(body);
 
const char * funname = GetDeclaredName(fun_declarator);
assert(funname);
Backend::new_function(funname);
 
int ret_size = ret_type->GetSize();
if (ret_size <= 4) ret_size = 0; // return value in register
ret_size += 2; // call return address
 
ParameterDeclarationList * pdl = ::GetParameters(fun_declarator);
 
int offset = ret_size;
for (ParameterDeclarationList * p = pdl; p; p = p->Tail())
{
ParameterDeclaration * pd = p->Head();
assert(pd);
offset += pd->AllocateParameters(offset);
}
 
const int autosize = body->EmitAutovars(out);
 
body->Emit(out);
Backend::ret(autosize);
EmitEnd(out);
 
Name::RemoveAuto();
}
//-----------------------------------------------------------------------------
void InitDeclarator::Emit(FILE * out)
{
EmitStart(out);
if (declarator) declarator->Emit(out);
// don't emit initializer
EmitEnd(out);
}
//-----------------------------------------------------------------------------
const char * InitDeclarator::GetDeclaredName(int skip)
{
const char * ret = ::GetDeclaredName(declarator);
 
assert(ret);
return ret;
}
//-----------------------------------------------------------------------------
int InitDeclarator::EmitAutovars(FILE * out, TypeSpecifier * typespec)
{
EmitStart(out);
assert(declarator);
declarator->Emit(out);
 
assert(typespec);
TypeName type(typespec, declarator);
const Specifier spec = typespec->GetType();
 
assert(!(spec & SC_TYPEDEF));
assert(!(spec & SC_EXTERN));
 
const int size = typespec->GetSize(declarator);
const char * name = ::GetDeclaredName(declarator);
assert(name);
 
Name::SetAutoPos(name, Backend::GetSP() - size);
 
const int ret = typespec->GetSize(declarator);
if (ret < 0)
{
type.Print(stderr);
assert(0);
}
 
if (initializer) initializer->InitAutovar(out, type.GetSUW());
else Backend::push_zero(ret);
 
EmitEnd(out);
return ret;
}
//-----------------------------------------------------------------------------
void InitDeclarator::Allocate(FILE * out, TypeSpecifier * typespec)
{
const Specifier spec = typespec->GetType();
 
if (spec & SC_TYPEDEF) return;
 
const char * name = ::GetDeclaredName(declarator);
assert(name);
 
if (spec & SC_EXTERN)
{
fprintf(out, "\t.EXTERN\tC%s\n", name);
}
else if (spec & SC_STATIC)
{
// forward declaration
fprintf(out, "\t.STATIC\tC%s\n", name);
}
else if (!IsFunction(declarator))
{
fprintf(out, "C%s:\t\t\t; \n", name);
if (initializer)
{
TypeName tn(typespec, declarator);
initializer->EmitValue(out, &tn);
}
else
{
const int size = typespec->GetSize(declarator);
for (int b = 0; b < size; b++)
fprintf(out, "\t.BYTE\t0\t\t\t; VOID [%d]\r\n", b);
}
}
}
//-----------------------------------------------------------------------------
Declaration::Declaration(TypeSpecifier * ds, InitDeclaratorList * il)
: Node("Declaration"),
base_type(ds),
init_list(il)
{
assert(ds);
 
for (InitDeclaratorList * i = init_list; i; i = i->Tail())
{
InitDeclarator * id = i->Head();
assert(id);
Declarator * decl = id->GetDeclarator();
 
const char * dn = ::GetDeclaredName(decl);
assert(dn);
 
assert(base_type);
const Specifier spec = base_type->GetType();
 
if (spec & SC_TYPEDEF)
{
const Specifier real_spec = (Specifier)(spec & ~SC_TYPEDEF);
TypeSpecifier * real_type = new TypeSpecifier(real_spec,
base_type->GetName(),
base_type->GetStructDecl());
Declarator * ret = 0;
for (Declarator * d = decl; d; d = d->Tail())
{
DeclItem * di = d->Head();
assert(di);
if (di->GetWhat() != DECL_NAME)
ret = new Declarator(di, ret);
}
 
TypeName * tn = new TypeName(real_type, ret);
TypedefName::Add(dn, tn);
}
else
{
TypeName * tn = new TypeName(base_type, decl);
 
if (spec & SC_EXTERN) Name::AddExtern(dn, tn);
else if (spec & SC_STATIC) Name::AddStatic(dn, tn);
else Name::AddAuto(dn, tn);
}
}
}
//-----------------------------------------------------------------------------
void Declaration::Emit(FILE * out)
{
EmitStart(out);
if (base_type) base_type->Emit(out);
// if (init_list) init_list->Emit(out);
 
Allocate(out);
 
EmitEnd(out);
Name::AutoToLocal();
}
//-----------------------------------------------------------------------------
void Declaration::Allocate(FILE * out)
{
for (InitDeclaratorList * il = init_list; il; il = il->Tail())
{
InitDeclarator * id = il->Head();
assert(id);
id->Allocate(out, base_type);
}
}
//-----------------------------------------------------------------------------
int Declaration::EmitAutovars(FILE * out)
{
int ret = 0;
 
for (InitDeclaratorList * il = init_list; il; il = il->Tail())
{
InitDeclarator * id = il->Head();
assert(id);
ret += id->EmitAutovars(out, base_type);
}
 
return ret;
}
//-----------------------------------------------------------------------------
void Ptr::Emit(FILE * out)
{
EmitStart(out);
if (decl_specs) decl_specs->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void Initializer::Emit(FILE * out)
{
// debug only: must call EmitValue() or EmitAutovars()
EmitStart(out);
if (skalar_value) skalar_value->Emit(out);
if (array_value) array_value ->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
void Initializer::EmitValue(FILE * out, TypeName * tn)
{
if (tn->IsUnion())
{
int union_size = tn->GetSize();
TypeName * first = tn->FirstUnionMember(union_size);
if (first) EmitValue(out, first);
return;
}
 
if (skalar_value)
{
if (tn->IsArray()) // char x[] = "abc" ?
{
if (tn->GetElementType()->GetSize() != 1)
{
fprintf(stderr,
"Initialization of array with skalar or string\n");
semantic_errors++;
return;
}
 
if (!skalar_value->IsStringConstant())
{
fprintf(stderr,
"Initialization of char array with non-string\n");
semantic_errors++;
return;
}
 
int len = tn->GetSize();
if (len == -1)
{
len = skalar_value->GetSize(); // x[] = "..."
tn->SetArrayLength(len);
}
 
StringConstant * sc = skalar_value->GetStringConstant();
assert(sc);
sc->EmitAndRemove(out, len);
return;
}
 
skalar_value->EmitInitialization(out, tn->GetSize());
return;
}
 
assert(array_value);
 
// array or struct...
// check for array
//
if (tn->IsArray())
{
int elements;
Expression * alen = tn->ArrayLength();
if (alen) // a[len]
{
elements = alen->GetConstantNumericValue();
}
else // a[]
{
elements = List<Initializer>::Length(array_value);
tn->SetArrayLength(elements);
}
 
TypeName * etype = tn->GetElementType();
assert(etype);
const int size = etype->GetSize();
int done = 0;
 
for (InitializerList * il = array_value; il; il = il->Tail())
{
if (done == elements)
{
fprintf(stderr, "Too many array initializers\n");
semantic_errors++;
return;
}
 
Initializer * in = il->Head();
assert(in);
in->EmitValue(out, etype);
done++;
}
 
// init unspecified array elements to 0
//
for (int b = done; b < elements; b++)
{
if (size == 1)
fprintf(out, "\t.BYTE\t0\t\t\t; VOID[%d]\r\n", b);
else if (size == 2)
fprintf(out, "\t.WORD\t0\t\t\t; VOID[%d]\r\n", b);
else
{
for (int i = 0; i < size; i++)
fprintf(out, "\t.BYTE\t0\t\t\t; VOID[%d]\r\n", b);
}
}
 
return;
}
 
// struct...
//
if (!tn->IsStruct())
{
fprintf(stderr, "Initialization of skalar type with array\n");
semantic_errors++;
return;
}
 
TypeSpecifier * ts = tn->GetTypeSpecifier();
assert(ts);
 
const char * sname = ts->GetName();
if (sname == 0)
{
fprintf(stderr, "No struct name in struct initializer\n");
semantic_errors++;
return;
}
 
StructDeclarationList * sdl = StructName::Find(sname);
if (sdl == 0)
{
fprintf(stderr, "No struct %s defined\n", sname);
semantic_errors++;
return;
}
 
InitializerList * il = array_value;
 
for (; sdl; sdl = sdl->Tail())
{
StructDeclaration * sd = sdl->Head();
assert(sd);
TypeSpecifier * ts = sd->GetSpecifier();
assert(ts);
 
for (StructDeclaratorList * sr = sd->GetDeclarators(); sr;
sr = sr->Tail())
{
StructDeclarator * sor = sr->Head();
assert(sor);
 
Declarator * decl = sor->GetDeclarator();
assert(decl);
 
const char * membname = sor->GetMemberName();
if (membname == 0) membname = "anonymous";
 
TypeName type(ts, decl);
if (il == 0)
{
const int size = type.GetSize();
if (size == 1)
fprintf(out, "\t.BYTE\t0\t\t\t; VOID %s\r\n", membname);
else if (size == 2)
fprintf(out, "\t.WORD\t0\t\t\t; VOID %s\r\n", membname);
else
{
for (int i = 0; i < size; i++)
fprintf(out, "\t.BYTE\t0\t\t\t; VOID %s\r\n", membname);
}
}
else
{
Initializer * ini = il->Head();
assert(ini);
il = il->Tail();
ini->EmitValue(out, &type);
}
}
}
}
//-----------------------------------------------------------------------------
int Initializer::InitAutovar(FILE * out, SUW suw)
{
int ret = 0;
 
assert( skalar_value || array_value);
assert(!skalar_value || !array_value);
 
EmitStart(out);
 
if (skalar_value)
{
ret = 1; if (suw == WO) ret = 2;
 
if (skalar_value->IsNumericConstant())
{
int value = skalar_value->GetConstantNumericValue();
if (value == 0)
{
Backend::push_zero(ret);
}
else
{
skalar_value->Emit(out);
Backend::push_rr(suw);
}
}
else
{
skalar_value->Emit(out);
Backend::push_rr(suw);
}
}
else
{
fprintf(stderr, "TODO: aggregate initializer\r\n");
}
 
EmitEnd(out);
return ret;
}
//-----------------------------------------------------------------------------
TypeName * TypeSpecifier::GetMemberType(const char * member)
{
const int is_union = spec & TS_UNION;
const int is_struct = spec & TS_STRUCT;
 
if (!is_union && !is_struct)
{
fprintf(stderr, "access member %s of non-aggregate\n", member);
semantic_errors++;
return 0;
}
 
StructDeclarationList * sdl = StructName::Find(name);
if (sdl == 0)
{
fprintf(stderr, "No struct %s defined\n", name);
semantic_errors++;
return 0;
}
 
for (; sdl ; sdl = sdl->Tail())
{
StructDeclaration * sd = sdl->Head();
assert(sd);
TypeName * st = sd->GetMemberType(name, member);
if (st) return st;
}
 
fprintf(stderr, "aggregate %s has no member %s\n", name, member);
semantic_errors++;
return 0;
}
//-----------------------------------------------------------------------------
int StructDeclaration::Emit(FILE * out, const char * struct_name, int pos,
bool is_union)
{
size = 0;
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
{
StructDeclarator * sd = sl->Head();
assert(sd);
 
if (is_union)
{
int tsize = sd->EmitMember(out, struct_name,
decl_specifiers, 0, true);
if (size < tsize) size = tsize;
}
else
{
size += sd->EmitMember(out, struct_name,
decl_specifiers, pos + size, false);
}
}
 
return size;
}
//-----------------------------------------------------------------------------
TypeName * StructDeclaration::GetMemberType(const char * struct_name,
const char * member)
{
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
{
StructDeclarator * sd = sl->Head();
assert(sd);
TypeName * st = sd->GetMemberType(decl_specifiers, member);
if (st) return st;
}
 
return 0;
}
//-----------------------------------------------------------------------------
TypeName * StructDeclaration::FirstUnionMember(int union_size) const
{
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
{
StructDeclarator * sd = sl->Head();
assert(sd);
TypeName * st = sd->FirstUnionMember(decl_specifiers, union_size);
if (st) return st;
}
 
return 0;
}
//-----------------------------------------------------------------------------
int StructDeclaration::GetMemberPosition(const char * struct_name,
const char * member,
bool is_union) const
{
if (is_union) return 0;
 
for (StructDeclaratorList * sl = struct_decl_list; sl ; sl = sl->Tail())
{
StructDeclarator * sd = sl->Head();
assert(sd);
int position = sd->GetMemberPosition(member);
if (position >= 0) return position;
}
 
return -1;
}
//-----------------------------------------------------------------------------
TypeName * StructDeclarator::GetMemberType(TypeSpecifier * tspec,
const char * member)
{
for (Declarator * decl = declarator; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
if (di->GetWhat() != DECL_NAME) continue;
assert(di->GetName());
if (strcmp(member, di->GetName())) continue;
return new TypeName(tspec, declarator);
}
 
return 0;
}
//-----------------------------------------------------------------------------
TypeName * StructDeclarator::FirstUnionMember(TypeSpecifier * tspec,
int union_size) const
{
for (Declarator * decl = declarator; decl; decl = decl->Tail())
{
TypeName tn(tspec, declarator);
if (tn.GetSize() != union_size) continue;
 
return new TypeName(tspec, declarator);
}
 
return 0;
}
//-----------------------------------------------------------------------------
const char * StructDeclarator::GetMemberName() const
{
for (Declarator * decl = declarator; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
if (di->GetWhat() != DECL_NAME) continue;
assert(di->GetName());
return di->GetName();
}
 
return 0;
}
//-----------------------------------------------------------------------------
int StructDeclarator::GetMemberPosition(const char * member) const
{
for (Declarator * decl = declarator; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
if (di->GetWhat() != DECL_NAME) continue;
assert(di->GetName());
if (strcmp(member, di->GetName())) continue;
return position;
}
 
return -1;
}
//-----------------------------------------------------------------------------
bool TypeSpecifier::IsNumericType() const
{
if (spec & TS_NUMERIC) return true;
if (spec != TS_TYPE_NAME) return false;
 
assert(name);
TypeName * tname = TypedefName::Find(name);
assert(tname);
return tname->IsNumericType();
}
//-----------------------------------------------------------------------------
int TypeSpecifier::GetBaseSize() const
{
if (spec & TS_VOID) return 0;
if (spec & TS_CHAR) return 1;
if (spec & TS_SHORT) return 2;
if (spec & TS_INT) return 2;
if (spec & TS_LONG) return 4;
if (spec & TS_FLOAT) return 4;
if (spec & TS_DOUBLE) return 8;
if (spec & TS_ENUM) return 2;
if (spec & (TS_STRUCT | TS_UNION))
{
assert(name);
StructDeclarationList * sdl = StructName::Find(name);
if (sdl == 0)
{
fprintf(stderr, "No struct %s defined\n", name);
semantic_errors++;
return 0;
}
 
int size = 0;
for (; sdl; sdl = sdl->Tail())
{
assert(sdl->Head());
int tsize = sdl->Head()->GetSize();
if (spec & TS_UNION)
{
if (size < tsize) size = tsize;
}
else
{
size += tsize;
}
}
return size;
}
 
if (spec & TS_TYPE_NAME)
{
assert(name);
TypeName * tname = TypedefName::Find(name);
assert(tname);
return tname->GetTypeSpecifier()->GetBaseSize();
}
 
return 2; // no type -> int
}
//-----------------------------------------------------------------------------
int TypeSpecifier::GetSize(Declarator * decl) const
{
int size = -2;
 
for (; decl; decl = decl->Tail())
{
const DeclItem * ditem = decl->Head();
assert(ditem);
 
switch(ditem->GetWhat())
{
case DECL_FUNPTR:
size = 2;
continue;
 
case DECL_POINTER:
size = 2;
continue;
 
case DECL_FUN:
size = 2;
continue;
 
case DECL_ARRAY:
if (ditem->GetArraySize()) // type[num]
{
if (size == -2) size = GetBaseSize();
size *= ditem->GetArraySize()
->GetConstantNumericValue();
}
else // type[]
{
size = -1;
}
continue;
 
case DECL_NAME:
continue; // varname
 
default: assert(0 && "BAD what");
}
}
 
if (size == -2) return GetBaseSize();
return size;
}
//-----------------------------------------------------------------------------
int TypeSpecifier::GetFunReturnSize(Declarator * decl) const
{
assert(this);
if (decl == 0)
{
fprintf(stderr, "Can't get parameters of (undeclared ?) function\n");
semantic_errors++;
return 0;
}
 
int base_size = GetBaseSize();
 
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
const Expression * asize = di->GetArraySize();
 
switch(di->GetWhat())
{
case DECL_NAME:
continue;
 
case DECL_FUNPTR:
base_size = 2;
continue;
 
case DECL_ARRAY:
if (asize == 0) // []
base_size = 2;
else // [const expr]
base_size *= asize->GetConstantNumericValue();
continue;
 
case DECL_FUN:
continue;
 
case DECL_POINTER:
base_size = 2;
continue;
 
default: assert(0 && "Bad InitDeclarator::what");
}
}
 
return base_size;
}
//-----------------------------------------------------------------------------
TypeSpecifier * TypeSpecifier::operator +(TypeSpecifier & other)
{
int sc_cnt = 0;
int tq_cnt = 0;
int si_cnt = 0;
int ty_cnt = 0;
 
if (spec & SC_MASK) sc_cnt++;
if (spec & TQ_MASK) tq_cnt++;
if (spec & TS_SIGN_MASK) si_cnt++;
if (spec & TS_MASK) ty_cnt++;
 
if (other.spec & SC_MASK) sc_cnt++;
if (other.spec & TQ_MASK) tq_cnt++;
if (other.spec & TS_SIGN_MASK) si_cnt++;
if (other.spec & TS_MASK) ty_cnt++;
 
if (sc_cnt > 1)
{
fprintf(stderr, "Multiple or contradicting storage class (ignored)\n");
semantic_errors++;
delete other.self();
return this;
}
 
if (tq_cnt > 1)
{
fprintf(stderr, "Multiple or contradicting qualifiers (ignored)\n");
semantic_errors++;
delete other.self();
return this;
}
 
if (si_cnt > 1)
{
fprintf(stderr,
"Multiple or Contradicting signed/unsigned (ignored)\n");
semantic_errors++;
delete other.self();
return this;
}
 
if (ty_cnt > 1)
{
fprintf(stderr, "Multiple or Contradicting types (ignored)\n");
semantic_errors++;
delete other.self();
return this;
}
 
if (other.enum_list) enum_list = other.enum_list;
if (other.name) name = other.name;
if (other.struct_decl_list) struct_decl_list = other.struct_decl_list;
 
spec = (Specifier)(spec | other.spec);
delete other.self();
return this;
}
//-----------------------------------------------------------------------------
int TypeSpecifier::Print(FILE * out) const
{
int len = 0;
 
if (spec & SC_TYPEDEF) len += fprintf(out, "typedef ");
if (spec & SC_EXTERN) len += fprintf(out, "extern ");
if (spec & SC_STATIC) len += fprintf(out, "static ");
if (spec & SC_AUTO) len += fprintf(out, "auto ");
if (spec & SC_REGISTER) len += fprintf(out, "register ");
 
if (spec & TQ_CONST) len += fprintf(out, "const ");
if (spec & TQ_VOLATILE) len += fprintf(out, "volatile ");
 
if (spec & TS_SIGNED) len += fprintf(out, "signed ");
if (spec & TS_UNSIGNED) len += fprintf(out, "unsigned ");
 
if (spec & TS_VOID) len += fprintf(out, "void ");
if (spec & TS_CHAR) len += fprintf(out, "char ");
if (spec & TS_SHORT) len += fprintf(out, "short ");
if (spec & TS_INT) len += fprintf(out, "int ");
if (spec & TS_LONG) len += fprintf(out, "long ");
if (spec & TS_FLOAT) len += fprintf(out, "float ");
if (spec & TS_DOUBLE) len += fprintf(out, "double ");
 
if (spec & TS_STRUCT)
{
assert(name);
len += fprintf(out, "struct '%s' ", name);
}
 
if (spec & TS_UNION)
{
assert(name);
len += fprintf(out, "union '%s' ", name);
}
 
if (spec & TS_ENUM)
{
if (name) len += fprintf(out, "enum '%s' ", name);
else len += fprintf(out, "anonymous enum ");
}
 
if (spec & TS_TYPE_NAME)
{
if (name) len += fprintf(out, "'%s' ", name);
else len += fprintf(out, "<user type> ");
}
 
return len;
}
//-----------------------------------------------------------------------------
// struct, union, or typedef
//
TypeSpecifier::TypeSpecifier(Specifier sp, const char * n,
StructDeclarationList * sdl)
: Node("TypeSpecifier (struct/union)"),
spec(sp),
name(n),
struct_decl_list(sdl),
enum_list(0)
{
if (name == 0) // anonymous struct or union
{
char * cp = new char[20];
sprintf(cp, "anonymous-%d", anonymous_number++);
name = cp;
}
 
if (struct_decl_list) StructName::Add(name, struct_decl_list);
}
//-----------------------------------------------------------------------------
void TypeSpecifier::Emit(FILE * out)
{
EmitStart(out);
EmitIndent(out);
fprintf(out, "spec = ");
 
Print(out);
 
fprintf(out, "(%X)\n", spec);
 
if (name)
{
EmitIndent(out);
fprintf(out, "name = %s\n", name);
}
 
if (struct_decl_list)
{
int pos = 0;
for (StructDeclarationList * sl = struct_decl_list; sl; sl = sl->Tail())
{
assert(sl->Head());
pos += sl->Head()->Emit(out, name, pos, IsUnion());
}
}
 
if (enum_list)
{
if (name) TypedefName::Add(name, new TypeName(TS_INT));
enum_list->Emit(out);
}
EmitEnd(out);
}
//-----------------------------------------------------------------------------
int Ptr::Print(FILE * out) const
{
return fprintf(out, "* ");
}
//-----------------------------------------------------------------------------
void DeclItem::SetArraySize(int len)
{
assert(!array_size);
assert(len >= 0);
array_size = new NumericExpression(len);
}
//-----------------------------------------------------------------------------
int DeclItem::Print(FILE * out) const
{
switch(what)
{
case DECL_FUNPTR: return fprintf(out, "*() ");
case DECL_ARRAY: if (!array_size) return fprintf(out, "[] ");
return fprintf(out, "[%d] ",
array_size->GetConstantNumericValue());
case DECL_FUN: return fprintf(out, "() ");
case DECL_POINTER: {
assert(pointer);
int len = 0;
for (Pointer * p = pointer; p; p = p->Tail())
len += p->Head()->Print(out);
return len;
}
case DECL_NAME: assert(name);
return fprintf(out, "%s ", name);
}
 
assert(0 ** "Bad what");
}
//-----------------------------------------------------------------------------
void DeclItem::Emit(FILE * out)
{
const char * s = "BAD DECL";
 
EmitStart(out);
switch(what)
{
case DECL_NAME: s = "DECL_NAME"; break;
case DECL_FUNPTR: s = "DECL_FUNPTR"; break;
case DECL_ARRAY: s = "DECL_ARRAY"; break;
case DECL_FUN: s = "DECL_FUN"; break;
case DECL_POINTER: s = "DECL_POINTER"; break;
}
EmitIndent(out);
fprintf(out, "what = %s\r\n", s);
 
if (name)
{
EmitIndent(out);
fprintf(out, "name = %s\r\n", name);
}
 
if (funptr) funptr->Emit(out);
// don't emit array_size
if (fun_params) fun_params->Emit(out);
if (fun_identifiers) fun_identifiers->Emit(out);
if (pointer) pointer->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
TypeName::TypeName(TypeSpecifier * ds, Declarator * ad)
: Node("TypeName"),
decl_spec(ds),
abs_declarator(ad)
{
assert(ds);
if (ds->GetType() & TS_TYPE_NAME)
{
const char * name = decl_spec->GetName();
assert(name);
 
TypeName * def = TypedefName::Find(name);
assert(def);
 
// copy type specifier from definition...
//
decl_spec = def->GetTypeSpecifier();
assert(decl_spec);
 
// prepend declarator from definition
//
for (Declarator * decl = def->abs_declarator->Reverse();
decl; decl = decl->Tail())
abs_declarator = new Declarator(decl->Head(), abs_declarator);
}
}
//-----------------------------------------------------------------------------
TypeName::TypeName(Specifier sp)
: Node("TypeName (internal)"),
decl_spec(new TypeSpecifier(sp)),
abs_declarator(0)
{
assert((sp & TS_TYPE_NAME) == 0);
}
//-----------------------------------------------------------------------------
void TypeName::Emit(FILE * out)
{
EmitStart(out);
if (decl_spec) decl_spec->Emit(out);
if (abs_declarator) abs_declarator->Emit(out);
EmitEnd(out);
}
//-----------------------------------------------------------------------------
SUW TypeName::GetSUW()
{
if (IsPointer()) return WO;
 
const int size = GetSize();
 
if (size == 2) return WO;
if (size != 1)
{
fprintf(stderr, "---- Size not 1 or 2:\n");
Emit(stderr);
fprintf(stderr, "\n====\n");
*(char*)0 = 0;
fprintf(stderr, "\n====\n");
}
assert(size == 1);
if (IsUnsigned()) return UB;
return SB;
}
//-----------------------------------------------------------------------------
bool TypeName::IsUnsigned() const
{
if (IsPointer()) return true;
return decl_spec->IsUnsigned();
}
//-----------------------------------------------------------------------------
bool TypeName::IsNumericType() const
{
if (!decl_spec->IsNumericType()) return false;
 
for (Declarator * d = abs_declarator; d; d = d->Tail())
{
DeclItem * di = d->Head();
assert(di);
switch(di->GetWhat())
{
case DECL_NAME: continue;
case DECL_FUNPTR: return false;
case DECL_ARRAY: return false;
case DECL_FUN: return true;
case DECL_POINTER: return false;
default: assert(0 && "Bad what");
}
}
return true;
}
//-----------------------------------------------------------------------------
TypeName * TypeName::GetFunReturnType()
{
assert(this);
 
if (abs_declarator)
{
Declarator * ret = 0;
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
{
DECL_WHAT what = decl->Head()->GetWhat();
if (what == DECL_FUNPTR || what == DECL_FUN)
return new TypeName(decl_spec, ret->Reverse());
 
ret = new Declarator(decl->Head(), ret);
}
}
 
Print(stderr);
fprintf(stderr, " is not a function\n");
semantic_errors++;
return new TypeName(TS_INT);
}
//-----------------------------------------------------------------------------
TypeName * TypeName::GetMemberType(const char * member)
{
TypeName * tn = decl_spec->GetMemberType(member);
if (tn) return tn;
 
const char * sname = decl_spec->GetName();
assert(sname);
 
fprintf(stderr, "aggregate %s has no member %s\n", sname, member);
semantic_errors++;
return this;
}
//-----------------------------------------------------------------------------
TypeName * TypeName::FirstUnionMember(int union_size) const
{
assert(IsUnion());
assert(decl_spec);
 
const char * uname = decl_spec->GetName();
assert(uname);
 
StructDeclarationList * sdl = StructName::Find(uname);
if (sdl == 0)
{
fprintf(stderr, "No struct %s defined\n", uname);
semantic_errors++;
return 0;
}
 
for (; sdl; sdl = sdl->Tail())
{
StructDeclaration * sd = sdl->Head();
assert(sd);
 
TypeName * ret = sd->FirstUnionMember(union_size);
if (ret) return ret;
}
 
assert(0);
}
//-----------------------------------------------------------------------------
TypeName * TypeName::AddressOf() const
{
assert(this);
assert(decl_spec);
 
Ptr * newptr = new Ptr(0);
 
if (abs_declarator == 0 || abs_declarator->Head()->GetWhat() != DECL_POINTER)
{
Pointer * pointer = new Pointer(newptr, 0);
DeclItem * di = new DeclItem(pointer);
Declarator * decl = new Declarator(di, abs_declarator);
return new TypeName(decl_spec, decl);
}
 
DeclItem * hd = abs_declarator->Head();
assert(hd);
assert(hd->GetWhat() == DECL_POINTER);
 
Pointer * pointer = new Pointer(newptr, hd->GetPointer());
DeclItem * di = new DeclItem(pointer);
Declarator * decl = new Declarator(di, abs_declarator->Tail());
return new TypeName(decl_spec, decl);
}
//-----------------------------------------------------------------------------
TypeName * TypeName::ContentOf() const
{
assert(this);
assert(decl_spec);
 
if (!abs_declarator)
{
semantic_errors++;
Print(stderr);
fprintf(stderr, " is not a pointer\n");
return new TypeName(new TypeSpecifier(TS_INT), 0);
}
 
DeclItem * hd = abs_declarator->Head();
assert(hd);
 
if (hd->GetWhat() != DECL_POINTER)
{
if (IsArray())
{
Declarator * ret = 0;
Declarator * last = 0;
for (Declarator * d = abs_declarator; d; d = d->Tail())
{
DeclItem * di = d->Head();
assert(di);
if (di->GetWhat() == DECL_ARRAY) last = d;
}
 
assert(last);
for (Declarator * d = abs_declarator; d; d = d->Tail())
{
if (d != last) ret = new Declarator(d->Head(), ret);
}
ret = ret->Reverse();
return new TypeName(decl_spec, ret);
}
semantic_errors++;
Print(stderr);
fprintf(stderr, " is not a pointer\n");
return new TypeName(new TypeSpecifier(TS_INT), 0);
}
 
Pointer * pointer = hd->GetPointer();
assert(pointer);
pointer = pointer->Tail();
if (!pointer) return new TypeName(decl_spec, abs_declarator->Tail());
 
DeclItem * new_hd = new DeclItem(pointer);
Declarator * decl = new Declarator(new_hd, abs_declarator->Tail());
return new TypeName(decl_spec, decl);
}
//-----------------------------------------------------------------------------
int TypeName::Print(FILE * out) const
{
assert(this);
 
int len = 0;
if (decl_spec) len += decl_spec->Print(out);
 
for (Declarator * dl = abs_declarator; dl; dl = dl->Tail())
{
DeclItem * di = dl->Head();
assert(di);
len += fprintf(out, " ");
len += di->Print(out);
}
 
return len;
}
//-----------------------------------------------------------------------------
const char * TypeName::GetDeclaredName()
{
const char * ret = 0;
 
for (Declarator * d = abs_declarator; d; d = d->Tail())
{
DeclItem * di = d->Head();
assert(di);
const char * n = di->GetName();
if (n == 0) continue;
assert (ret == 0);
ret = n;
}
 
return ret;
}
//-----------------------------------------------------------------------------
const char * GetDeclaredName(Declarator * decl)
{
const char * ret = 0;
int count = 0;
 
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
switch(di->GetWhat())
{
case DECL_NAME: ret = di->GetName();
assert(ret);
count++;
continue;
 
case DECL_FUNPTR: assert(!di->GetName());
assert(di->GetFunptr());
ret = GetDeclaredName(di->GetFunptr());
assert(ret);
count++;
continue;
 
case DECL_ARRAY:
case DECL_FUN:
case DECL_POINTER: assert(!di->GetName());
continue;
 
default: assert("Bad What");
 
}
}
 
assert(count <= 1);
return ret;
}
//-----------------------------------------------------------------------------
int TypeName::GetPointeeSize() const
{
assert(abs_declarator);
assert(IsPointer() || IsArray());
 
return ContentOf()->GetSize();
}
//-----------------------------------------------------------------------------
bool TypeName::IsPointer() const
{
if (abs_declarator) return ::IsPointer(abs_declarator);
return false;
}
//-----------------------------------------------------------------------------
bool TypeName::IsArray() const
{
if (abs_declarator) return ::IsArray(abs_declarator);
return false;
}
//-----------------------------------------------------------------------------
TypeName * TypeName::GetElementType() const
{
DeclItem * last = 0;
 
assert(abs_declarator);
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_ARRAY) last = di;
}
 
assert(last);
 
// copy decl items except name and last...
//
Declarator * ret = 0;
for (Declarator * decl = abs_declarator; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
if (di == last) continue;
if (di->GetWhat() == DECL_NAME) continue;
 
ret = new Declarator(di, ret);
}
 
 
return new TypeName(decl_spec, ret);
}
//-----------------------------------------------------------------------------
void TypeName::SetArrayLength(int len)
{
assert(abs_declarator);
::SetArrayLength(abs_declarator, len);
}
//-----------------------------------------------------------------------------
Expression * TypeName::ArrayLength() const
{
if (abs_declarator) return ::ArrayLength(abs_declarator);
return 0;
}
//-----------------------------------------------------------------------------
bool TypeName::IsStruct() const
{
assert(decl_spec);
if (decl_spec->GetType() & TS_STRUCT) return true;
return false;
}
//-----------------------------------------------------------------------------
bool TypeName::IsUnion() const
{
assert(decl_spec);
if (decl_spec->GetType() & TS_UNION) return true;
return false;
}
//-----------------------------------------------------------------------------
bool IsPointer(Declarator * decl)
{
assert(decl);
 
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_POINTER) return true;
return false;
}
//-----------------------------------------------------------------------------
bool IsArray(Declarator * decl)
{
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_ARRAY) return true;
}
 
return false;
}
//-----------------------------------------------------------------------------
Expression * ArrayLength(Declarator * decl)
{
DeclItem * last = 0;
 
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_ARRAY) last = di;
}
 
if (last) return last->GetArraySize();
return 0;
}
//-----------------------------------------------------------------------------
void SetArrayLength(Declarator * decl, int len)
{
DeclItem * last = 0;
 
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_ARRAY) last = di;
}
 
assert(last);
last->SetArraySize(len);
}
//-----------------------------------------------------------------------------
bool IsFunPtr(Declarator * decl)
{
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_FUNPTR) return true;
}
 
return false;
}
//-----------------------------------------------------------------------------
bool IsFunction(Declarator * decl)
{
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_FUN) return true;
}
 
return false;
}
//-----------------------------------------------------------------------------
ParameterDeclarationList * GetParameters(Declarator * decl)
{
for (; decl; decl = decl->Tail())
{
DeclItem * di = decl->Head();
assert(di);
 
if (di->GetWhat() == DECL_FUN) return di->GetParameters();
if (di->GetWhat() == DECL_FUNPTR) return di->GetParameters();
}
 
fprintf(stderr, "Can't get parameters of undeclared function\n");
return 0;
}
//-----------------------------------------------------------------------------
/ansic.flex
0,0 → 1,355
 
D [0-9]
L [a-zA-Z_]
NQ [\x20-\x21\x23-\x5B\x5D-\x7E]
H [a-fA-F0-9]
E [Ee][+-]?{D}+
FS (f|F|l|L)
IS (u|U|l|L)*
 
%x com
%x strg
 
%{
#include <stdio.h>
#include "Node.hh"
#include "Name.hh"
#include "ansic_bison.cc.h"
 
extern FILE * out;
 
void count();
int check_type();
int StringConstant::str_count = 0;
StringConstant * StringConstant::
all_strings[StringConstant::MAX_STRINGS] = { 0 };
 
%}
 
%%
"//".* { count(); }
"/*" { count(); BEGIN(com); }
<com>"*/" { count(); BEGIN(0); }
<com>\r { count(); }
<com>\n { count(); }
<com>. { count(); }
 
"ASM" { count(); return(ASM); }
"auto" { count(); return(AUTO); }
"break" { count(); return(BREAK); }
"case" { count(); return(CASE); }
"char" { count(); return(CHAR); }
"const" { count(); return(CONST); }
"continue" { count(); return(CONTINUE); }
"default" { count(); return(DEFAULT); }
"do" { count(); return(DO); }
"double" { count(); return(DOUBLE); }
"else" { count(); return(ELSE); }
"enum" { count(); return(ENUM); }
"extern" { count(); return(EXTERN); }
"float" { count(); return(FLOAT); }
"for" { count(); return(FOR); }
"goto" { count(); return(GOTO); }
"if" { count(); return(IF); }
"int" { count(); return(INT); }
"long" { count(); return(LONG); }
"register" { count(); return(REGISTER); }
"return" { count(); return(RETURN); }
"short" { count(); return(SHORT); }
"signed" { count(); return(SIGNED); }
"sizeof" { count(); return(SIZEOF); }
"static" { count(); return(STATIC); }
"struct" { count(); return(STRUCT); }
"switch" { count(); return(SWITCH); }
"typedef" { count(); return(TYPEDEF); }
"union" { count(); return(UNION); }
"unsigned" { count(); return(UNSIGNED); }
"void" { count(); return(VOID); }
"volatile" { count(); return(VOLATILE); }
"while" { count(); return(WHILE); }
 
{L}({L}|{D})* { count(); yylval._name = new char[strlen(yytext)+1];
strcpy((char *)(yylval._name), yytext);
return(check_type()); }
 
0[xX]{H}+{IS}? { count(); yylval._num = new NumericConstant(yytext);
return(CONSTANT); }
0{D}+{IS}? { count(); yylval._num = new NumericConstant(yytext);
return(CONSTANT); }
{D}+{IS}? { count(); yylval._num = new NumericConstant(yytext);
return(CONSTANT); }
L?'(\\.|[^\\'])+' { count(); yylval._num = new NumericConstant(yytext);
return(CONSTANT); }
{D}+{E}{FS}? { count(); yylval._num = 0; /* TODO */
return(CONSTANT); }
{D}*"."{D}+({E})?{FS}? { count(); yylval._num = 0; /* TODO */
return(CONSTANT); }
{D}+"."{D}*({E})?{FS}? { count(); yylval._num = 0; /* TODO */
return(CONSTANT); }
 
L?\" { count(); BEGIN(strg);
yylval._string_constant = new StringConstant(); }
<strg>\" { count(); BEGIN(0); return(STRING_LITERAL); }
<strg>\\\" { count(); *yylval._string_constant += '"'; }
<strg>\\a { count(); *yylval._string_constant += '\a'; }
<strg>\\b { count(); *yylval._string_constant += '\b'; }
<strg>\\f { count(); *yylval._string_constant += '\f'; }
<strg>\\n { count(); *yylval._string_constant += '\n'; }
<strg>\\r { count(); *yylval._string_constant += '\r'; }
<strg>\\t { count(); *yylval._string_constant += '\t'; }
<strg>{NQ} { count(); *yylval._string_constant += *yytext; }
<strg>\t { count(); *yylval._string_constant += '\t'; }
<strg>\r { count(); }
<strg>\n { count(); *yylval._string_constant += '\n'; }
<strg>. { count(); *yylval._string_constant += *yytext; }
 
"..." { count(); return(ELLIPSIS); }
">>=" { count(); return(RIGHT_ASSIGN); }
"<<=" { count(); return(LEFT_ASSIGN); }
"+=" { count(); return(ADD_ASSIGN); }
"-=" { count(); return(SUB_ASSIGN); }
"*=" { count(); return(MUL_ASSIGN); }
"/=" { count(); return(DIV_ASSIGN); }
"%=" { count(); return(MOD_ASSIGN); }
"&=" { count(); return(AND_ASSIGN); }
"^=" { count(); return(XOR_ASSIGN); }
"|=" { count(); return(OR_ASSIGN); }
">>" { count(); return(RIGHT_OP); }
"<<" { count(); return(LEFT_OP); }
"++" { count(); return(INC_OP); }
"--" { count(); return(DEC_OP); }
"->" { count(); return(PTR_OP); }
"&&" { count(); return(AND_OP); }
"||" { count(); return(OR_OP); }
"<=" { count(); return(LE_OP); }
">=" { count(); return(GE_OP); }
"==" { count(); return(EQ_OP); }
"!=" { count(); return(NE_OP); }
";" { count(); return(';'); }
("{"|"<%") { count(); return('{'); }
("}"|"%>") { count(); return('}'); }
"," { count(); return(','); }
":" { count(); return(':'); }
"=" { count(); return('='); }
"(" { count(); return('('); }
")" { count(); return(')'); }
("["|"<:") { count(); return('['); }
("]"|":>") { count(); return(']'); }
"." { count(); return('.'); }
"&" { count(); return('&'); }
"!" { count(); return('!'); }
"~" { count(); return('~'); }
"-" { count(); return('-'); }
"+" { count(); return('+'); }
"*" { count(); return('*'); }
"/" { count(); return('/'); }
"%" { count(); return('%'); }
"<" { count(); return('<'); }
">" { count(); return('>'); }
"^" { count(); return('^'); }
"|" { count(); return('|'); }
"?" { count(); return('?'); }
 
[ \t\v\n\f] { count(); }
 
<<EOF>> { return EOFILE; };
. { return ERROR ; };
%%
 
int yywrap()
{
return(1);
}
 
int column = 0;
int row = 1;
 
//-----------------------------------------------------------------------------
enum { QUOTE = '\'', BACKSLASH = '\\' };
 
NumericConstant::NumericConstant(const char * txt)
: Constant("NumericConstant"),
size(0)
{
if (*txt == 'L') txt++;
if (*txt == QUOTE) // TODO: make it proper
{
value = 0;
for (txt++; *txt != QUOTE; txt++)
{
value <<= 8;
int next_val = *txt;
if (*txt == BACKSLASH)
{
txt++; // skip backslash
next_val = *txt;
switch(*txt)
{
case 'a': next_val = '\a'; break;
case 'b': next_val = '\b'; break;
case 'f': next_val = '\f'; break;
case 'n': next_val = '\n'; break;
case 'r': next_val = '\r'; break;
case 't': next_val = '\t'; break;
 
case '0': // octal
{
int len;
int s = sscanf(txt, "%i%n", &next_val, &len);
assert(s == 2);
txt += len;
}
break;
 
case 'x': // hex
{
int len;
txt++; // skip 'x'
int s = sscanf(txt, "%x%n", &next_val, &len);
assert(s == 2);
txt += len;
}
break;
}
}
value |= 0x00FF & next_val;
}
return;
}
 
if (txt[1] == 'x' || txt[1] == 'X')
{
assert(*txt == '0');
int cnt = sscanf(txt + 2, "%X", &value);
assert(cnt == 1);
return;
}
 
if (*txt == '0')
{
int cnt = sscanf(txt, "%o", &value);
assert(cnt == 1);
return;
}
 
int cnt = sscanf(txt, "%d", &value);
assert(cnt == 1);
}
//-----------------------------------------------------------------------------
StringConstant::StringConstant()
: Constant("StringConstant"),
buffer(new char[80]),
buffer_len(80),
string_number(str_count++),
value_len(0)
{
assert(buffer);
*buffer = 0;
if (string_number == 0) // first string
{
for (int i = 0; i < MAX_STRINGS; i++) all_strings[i] = 0;
}
 
all_strings[string_number] = this;
}
//-----------------------------------------------------------------------------
void StringConstant::EmitAll(FILE * out)
{
for (int i = 0; i < MAX_STRINGS; i++)
{
StringConstant * sc = all_strings[i];
if (sc == NULL) continue;
 
fprintf(out, "Cstr_%d:\t\t\t\t;\n", sc->string_number);
for (int i = 0; i < sc->value_len; i++)
fprintf(out, "\t.BYTE\t0x%2.2X\t\t\t;\n", sc->buffer[i]);
 
fprintf(out, "\t.BYTE\t0\t\t\t;\n");
}
}
//-----------------------------------------------------------------------------
void StringConstant::EmitAndRemove(FILE * out, int length)
{
if (length < (value_len + 1))
{
fprintf(stderr,
"Initialization string too long (length %d, size %d)\n",
value_len + 1, length);
semantic_errors++;
}
 
for (int b = 0; b < length; b++)
{
if (b > value_len)
fprintf(out, "\t.BYTE\t0\t\t\t; [%d]\n", b);
else
fprintf(out, "\t.BYTE\t0x%2.2X\t\t\t; [%d]\n", buffer[b], b);
}
all_strings[string_number] = 0;
}
//-----------------------------------------------------------------------------
StringConstant::~StringConstant()
{
delete buffer;
 
assert(all_strings[string_number] == this);
all_strings[string_number] = 0;
}
//-----------------------------------------------------------------------------
StringConstant * StringConstant::operator & (StringConstant * other)
{
buffer_len = value_len + other->value_len;
char * cp = new char[buffer_len + 1];
assert(cp);
memcpy(cp, buffer, value_len);
memcpy(cp + value_len, other->buffer, other->value_len);
cp[buffer_len] = 0;
value_len += other->value_len;
 
delete buffer;
buffer = cp;
delete other;
return this;
}
//-----------------------------------------------------------------------------
void StringConstant::operator += (char txt)
{
if (value_len + 1 >= buffer_len)
{
assert(buffer);
 
char * cp = new char[2*buffer_len];
assert(cp);
memcpy(cp, buffer, buffer_len);
delete buffer;
buffer = cp;
buffer_len *= 2;
}
 
buffer[value_len++] = txt;
buffer[value_len] = 0;
}
//-----------------------------------------------------------------------------
void count()
{
for (int i = 0; yytext[i]; i++)
{
if (yytext[i] == '\n') { column = 0; row++; }
else if (yytext[i] == '\t') column += 8 - (column % 8);
else column++;
}
}
//-----------------------------------------------------------------------------
int check_type()
{
if (TypedefName::IsDefined(yytext)) return TYPE_NAME;
return(IDENTIFIER);
}
//-----------------------------------------------------------------------------
int yyerror(const char *s)
{
printf("\n%s Line %d Col %d\n", s, row, column);
fflush(stdout);
}
//-----------------------------------------------------------------------------
/Backend.cc
0,0 → 1,807
 
#include <stdio.h>
#include <string.h>
#include <assert.h>
 
#include "Backend.hh"
#include "Node.hh"
 
extern bool is_loader;
extern int memtop;
 
int Backend::stack_pointer = 0;
int Backend::label_num = 1;
int Backend::function_num = 1;
 
//-----------------------------------------------------------------------------
int Backend::check_size(int size, const char * function)
{
if (size == 1) return 8;
if (size == 2) return 16;
fprintf(stderr, "Backend::%s does not support %d bits\n", size * 8);
return 0;
}
//-----------------------------------------------------------------------------
int Backend::check_size(SUW suw, const char * function)
{
if (suw == SB) return 8;
else if (suw == UB) return 8;
else if (suw == WO) return 16;
assert(0);
}
//-----------------------------------------------------------------------------
void Backend::file_header()
{
if (is_loader)
fprintf(out,
"IN_RX_DATA\t= 0x00\t\t\t;\n"
"IN_STATUS\t= 0x01\t\t\t;\n"
"\n"
"MEMTOP\t\t= 0x%4.4X\n"
"\n"
"OUT_TX_DATA\t= 0x00\t\t\t;\n"
";---------------------------------------;\n"
"RELOC_SRC\t= start+Cend_text-stack\t;\n"
";---------------------------------------;\n"
"\t\t\t\t\t;\n"
"\tMOVE\t#reloc_rr, RR\t\t;\n"
"\tMOVE\tRR, SP\t\t\t;\n"
"\tMOVE\t#MEMTOP, LL\t\t; destination\n"
"reloc:\t\t\t\t\t;\n"
"\tMOVE\t(SP)+, RR\t\t; restore source\n"
"\tMOVE\t-(RR), -(LL)\t\t;\n"
"\tMOVE\tRR, -(SP)\t\t; save source\n"
"\tSHI\tRR, #start\t\t;\n"
"\tJMP\tRRNZ, reloc\t\t;\n"
"\tMOVE\t#stack, RR\t\t;\n"
"\tMOVE\tRR, SP\t\t\t;\n"
"\tCALL\tCmain\t\t\t;\n"
"halt:\t\t\t\t\t;\n"
"\tHALT\t\t\t\t;\n"
"reloc_rr:\t\t\t\t; source\n"
"\t.WORD\tRELOC_SRC\t\t;\n"
";---------------------------------------;\n"
"start:\t\t\t\t\t;\n"
"\t.OFFSET\tMEMTOP\t\t\t;\n"
"stack:\t\t\t\t\t;\n"
";---------------------------------------;\n", memtop);
else
fprintf(out,
"IN_RX_DATA\t\t= 0x00\t\t;\n"
"IN_STATUS\t\t= 0x01\t\t;\n"
"IN_TEMPERAT\t\t= 0x02\t\t;\n"
"IN_DIP_SWITCH\t\t= 0x03\t\t;\n"
"IN_CLK_CTR_LOW\t\t= 0x05\t\t;\n"
"IN_CLK_CTR_HIGH\t\t= 0x06\t\t;\n"
"\n"
"MEMTOP\t=0x%4.4X\n"
"\n"
"OUT_TX_DATA\t\t= 0x00\t\t;\n"
"OUT_LEDS\t\t= 0x02\t\t;\n"
"OUT_INT_MASK\t\t= 0x03\t\t;\n"
"OUT_RESET_TIMER\t\t= 0x04\t\t;\n"
"OUT_START_CLK_CTR\t= 0x05\t\t;\n"
"OUT_STOP_CLK_CTR\t= 0x06\t\t;\n"
";---------------------------------------;\n"
"\tMOVE\t#MEMTOP, RR\t\t;\n"
"\tMOVE\tRR, SP\t\t\t;\n"
"\tEI\t\t\t\t;\n"
"\tJMP\tCmain\t\t\t;\n"
"\tJMP\tCinterrupt\t\t;\n"
";---------------------------------------;\n"
"mult_div:\t\t\t\t;\n"
"\tMD_STP\t\t\t\t; 1\n"
"\tMD_STP\t\t\t\t; 2\n"
"\tMD_STP\t\t\t\t; 3\n"
"\tMD_STP\t\t\t\t; 4\n"
"\tMD_STP\t\t\t\t; 5\n"
"\tMD_STP\t\t\t\t; 6\n"
"\tMD_STP\t\t\t\t; 7\n"
"\tMD_STP\t\t\t\t; 8\n"
"\tMD_STP\t\t\t\t; 9\n"
"\tMD_STP\t\t\t\t; 10\n"
"\tMD_STP\t\t\t\t; 11\n"
"\tMD_STP\t\t\t\t; 12\n"
"\tMD_STP\t\t\t\t; 13\n"
"\tMD_STP\t\t\t\t; 14\n"
"\tMD_STP\t\t\t\t; 15\n"
"\tMD_STP\t\t\t\t; 16\n"
"\tRET\t\t\t\t;\n"
";---------------------------------------;\n", memtop);
}
//-----------------------------------------------------------------------------
void Backend::file_footer()
{
fprintf(out, "Cend_text:\t\t\t\t;\n");
}
//-----------------------------------------------------------------------------
int Backend::new_function(const char * fname)
{
fprintf(out, "C%s:\n", fname);
fflush(out);
assert(stack_pointer == 0);
function_num++;
}
//-----------------------------------------------------------------------------
void Backend::asmbl(const char * asm_string)
{
if (*asm_string == ' ') fprintf(out, "\t%s\n", asm_string + 1);
else fprintf(out, "%s\n", asm_string);
 
char buffer[256];
int bufidx = 0;
bool inside = true;
 
for (;;)
{
char c = *asm_string++;
switch(c)
{
case 0:
case '\r':
case '\n': buffer[bufidx] = 0;
asm_adjust(buffer);
bufidx = 0;
inside = true;
if (c == 0) return;
break;
 
case ';' : inside = false;
break;
 
case ' ': break; // ignore spaces
 
default: assert(bufidx < (sizeof(buffer) - 3));
if (inside) buffer[bufidx++] = c;
}
}
}
//-----------------------------------------------------------------------------
void Backend::asm_adjust(const char * asm_line)
{
int osp = stack_pointer;
bool need_adjust = false;
 
if (strstr(asm_line, "-(SP)"))
{
need_adjust = true;
if (strstr(asm_line, "RR,")) stack_pointer -= 2;
else if (strstr(asm_line, "R,")) stack_pointer -= 1;
else if (strstr(asm_line, "CLRW")) stack_pointer -= 2;
else if (strstr(asm_line, "CLRB")) stack_pointer -= 1;
}
 
if (strstr(asm_line, "(SP)+"))
{
need_adjust = true;
if (strstr(asm_line, ",RR")) stack_pointer += 2;
else if (strstr(asm_line, ",RS")) stack_pointer += 1;
else if (strstr(asm_line, ",RU")) stack_pointer += 1;
else if (strstr(asm_line, ",LL")) stack_pointer += 2;
else if (strstr(asm_line, ",LS")) stack_pointer += 1;
else if (strstr(asm_line, ",LU")) stack_pointer += 1;
}
 
if (need_adjust && osp == stack_pointer)
{
fprintf(out, "Bad ASM()\n");
Node::Error();
}
}
//-----------------------------------------------------------------------------
void Backend::load_rr_string(int snum, int offset)
{
fprintf(out, ";--\tload_rr_string\n");
 
if (offset) fprintf(out, "\tMOVE\t#Cstr_%d + %d, RR\n", snum, offset);
else fprintf(out, "\tMOVE\t#Cstr_%d, RR\n", snum);
}
//-----------------------------------------------------------------------------
void Backend::load_ll_string(int snum, int offset)
{
fprintf(out, ";--\tload_ll_string\n");
 
if (offset) fprintf(out, "\tMOVE\t#Cstr_%d + %d, LL\n", snum, offset);
else fprintf(out, "\tMOVE\t#Cstr_%d, LL\n", snum);
}
//-----------------------------------------------------------------------------
void Backend::load_rr_constant(int constant)
{
fprintf(out, ";--\tload_rr_constant\n");
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", constant & 0xFFFF);
}
//-----------------------------------------------------------------------------
void Backend::load_ll_constant(int constant)
{
fprintf(out, ";--\tload_ll_constant\n");
fprintf(out, "\tMOVE\t#0x%4.4X, LL\n", constant & 0xFFFF);
}
//-----------------------------------------------------------------------------
void Backend::load_rr_var(const char * name, SUW suw)
{
fprintf(out, ";--\tload_rr_var %s, (%d bit)\n",
name, check_size(suw, "load_rr_var"));
if (suw == SB) fprintf(out, "\tMOVE\t(C%s), RS\n", name);
else if (suw == UB) fprintf(out, "\tMOVE\t(C%s), RU\n", name);
else fprintf(out, "\tMOVE\t(C%s), RR\n", name);
}
//-----------------------------------------------------------------------------
void Backend::load_ll_var(const char * name, SUW suw)
{
fprintf(out, ";--\tload_ll_var %s, (%d bit)\n",
name, check_size(suw, "load_ll_var"));
if (suw == SB) fprintf(out, "\tMOVE\t(C%s), LS\n", name);
else if (suw == UB) fprintf(out, "\tMOVE\t(C%s), LU\n", name);
else fprintf(out, "\tMOVE\t(C%s), LL\n", name);
}
//-----------------------------------------------------------------------------
void Backend::load_rr_var(const char * name, int sp_off, SUW suw)
{
fprintf(out, ";--\tload_rr_var %s = %d(FP), SP at %d (%d bit)\n",
name, sp_off, GetSP(), check_size(suw, "load_rr_var"));
 
sp_off -= GetSP();
if (suw == SB) fprintf(out, "\tMOVE\t%d(SP), RS\n", sp_off);
else if (suw == UB) fprintf(out, "\tMOVE\t%d(SP), RU\n", sp_off);
else fprintf(out, "\tMOVE\t%d(SP), RR\n", sp_off);
}
//-----------------------------------------------------------------------------
void Backend::load_ll_var(const char * name, int sp_off, SUW suw)
{
fprintf(out, ";--\tload_ll_var %s = %d(FP), SP at %d (%d bit)\n",
name, sp_off, GetSP(), check_size(suw, "load_ll_var"));
 
sp_off -= GetSP();
if (suw == SB) fprintf(out, "\tMOVE\t%d(SP), LS\n", sp_off);
else if (suw == UB) fprintf(out, "\tMOVE\t%d(SP), LU\n", sp_off);
else fprintf(out, "\tMOVE\t%d(SP), LL\n", sp_off);
}
//-----------------------------------------------------------------------------
void Backend::store_rr_var(const char * name, SUW suw)
{
fprintf(out, ";--\tstore_rr_var %s\n", name);
if (suw == WO) fprintf(out, "\tMOVE\tRR, (C%s)\n", name);
else fprintf(out, "\tMOVE\tR, (C%s)\n", name);
}
//-----------------------------------------------------------------------------
void Backend::store_rr_var(const char * name, int sp_off, SUW suw)
{
fprintf(out, ";--\tstore_rr_var %s = %d(FP), SP at %d\n",
name, sp_off, GetSP());
 
sp_off -= GetSP();
if (suw == WO) fprintf(out, "\tMOVE\tRR, %d(SP)\n", sp_off);
else fprintf(out, "\tMOVE\tR, %d(SP)\n", sp_off);
}
//-----------------------------------------------------------------------------
void Backend::load_address(const char * name)
{
fprintf(out, ";--\tload_address %s\n", name);
fprintf(out, "\tMOVE\t#C%s, RR\n", name);
}
//-----------------------------------------------------------------------------
void Backend::load_address(const char * name, int sp_offset)
{
fprintf(out, ";--\tload_address %s = %d(FP), SP at %d\n",
name, sp_offset, GetSP());
fprintf(out, "\tLEA\t%d(SP), RR\n", sp_offset - GetSP());
}
//-----------------------------------------------------------------------------
void Backend::add_address(const char * name)
{
fprintf(out, ";--\tadd_address %s\n", name);
fprintf(out, "\tADD\tRR, #C%s\n", name);
}
//-----------------------------------------------------------------------------
void Backend::assign(int size)
{
fprintf(out, ";--\tassign (%d bit)\n", check_size(size, "assign"));
if (size == 1) fprintf(out, "\tMOVE\tR, (LL)\n");
else fprintf(out, "\tMOVE\tRR, (LL)\n");
}
//-----------------------------------------------------------------------------
void Backend::call(const char * name)
{
fprintf(out, ";--\tcall\n");
fprintf(out, "\tCALL\tC%s\n", name);
}
//-----------------------------------------------------------------------------
void Backend::call_ptr()
{
fprintf(out, ";--\tcall_ptr\n");
fprintf(out, "\tCALL\t(RR)\n");
}
//-----------------------------------------------------------------------------
void Backend::ret(int autosize)
{
fprintf(out, ";--\tret\n");
fprintf(out, "L%d_return:\n", function_num);
pop(autosize);
fprintf(out, "\tRET\n");
}
//-----------------------------------------------------------------------------
void Backend::push_rr(SUW suw)
{
fprintf(out, ";--\tpush_rr (%d bit)\n", check_size(suw, "push_rr"));
if (suw == WO) fprintf(out, "\tMOVE\tRR, -(SP)\n");
else fprintf(out, "\tMOVE\tR, -(SP)\n");
 
stack_pointer--;
if (suw == WO) stack_pointer--;
}
//-----------------------------------------------------------------------------
void Backend::pop_rr(SUW suw)
{
fprintf(out, ";--\tpop_rr (%d bit)\n", check_size(suw, "pop_rr"));
if (suw == SB) fprintf(out, "\tMOVE\t(SP)+, RS\n");
else if (suw == UB) fprintf(out, "\tMOVE\t(SP)+, RU\n");
else fprintf(out, "\tMOVE\t(SP)+, RR\n");
 
stack_pointer++;
if (suw == WO) stack_pointer++;
}
//-----------------------------------------------------------------------------
void Backend::pop_ll(SUW suw)
{
fprintf(out, ";--\tpop_ll (%d bit)\n", check_size(suw, "pop_ll"));
if (suw == SB) fprintf(out, "\tMOVE\t(SP)+, LS\n");
else if (suw == UB) fprintf(out, "\tMOVE\t(SP)+, LU\n");
else fprintf(out, "\tMOVE\t(SP)+, LL\n");
 
stack_pointer++;
if (suw == WO) stack_pointer++;
}
//-----------------------------------------------------------------------------
void Backend::pop(int pushed)
{
fprintf(out, ";--\tpop %d bytes\n", pushed);
assert(pushed >= 0);
stack_pointer += pushed;
 
if (pushed) fprintf(out, "\tADD\tSP, #%d\n", pushed);
}
//-----------------------------------------------------------------------------
void Backend::pop_return(int ret_bytes)
{
fprintf(out, ";--\tpop_return %d bytes\n", ret_bytes);
if (ret_bytes > 4) pop(ret_bytes);
}
//-----------------------------------------------------------------------------
int Backend::push_return(int ret_bytes)
{
fprintf(out, ";--\tpush %d bytes\n", ret_bytes);
if (ret_bytes <= 4) return 0;
push_zero(ret_bytes);
return ret_bytes;
}
//-----------------------------------------------------------------------------
void Backend::push_zero(int bytes)
{
fprintf(out, ";--\tpush_zero %d bytes\n", bytes);
stack_pointer -= bytes; // doesn't really matter
 
for (; bytes > 1; bytes -= 2) fprintf(out, "\tCLRW\t-(SP)\n");
if (bytes) fprintf(out, "\tCLRB\t-(SP)\n");
}
//-----------------------------------------------------------------------------
void Backend::move_rr_to_ll()
{
fprintf(out, ";--\tmove_rr_to_ll\n");
fprintf(out, "\tMOVE\tRR, LL\n");
}
//-----------------------------------------------------------------------------
void Backend::label(int lab)
{
fprintf(out, "L%d_%d:\n", function_num, lab);
}
//-----------------------------------------------------------------------------
void Backend::label(const char * name)
{
fprintf(out, "L%d_%s:\n", function_num, name);
}
//-----------------------------------------------------------------------------
void Backend::label(const char * name, int loop)
{
fprintf(out, "L%d_%s_%d:\n", function_num, name, loop);
}
//-----------------------------------------------------------------------------
void Backend::label(const char * name, int loop, int value)
{
fprintf(out, "L%d_%s_%d_%4.4X:\n", function_num, name, loop, value & 0xFFFF);
}
//-----------------------------------------------------------------------------
void Backend::branch(int lab)
{
fprintf(out, ";--\tbranch\n");
fprintf(out, "\tJMP\tL%d_%d\n", function_num, lab);
}
//-----------------------------------------------------------------------------
void Backend::branch(const char * name)
{
fprintf(out, ";--\tbranch\n");
fprintf(out, "\tJMP\tL%d_%s\n", function_num, name);
}
//-----------------------------------------------------------------------------
void Backend::branch(const char * name, int loop)
{
fprintf(out, ";--\tbranch\n");
fprintf(out, "\tJMP\tL%d_%s_%d\n", function_num, name, loop);
}
//-----------------------------------------------------------------------------
void Backend::branch_true(const char * name, int loop, int size)
{
fprintf(out, ";--\tbranch_true\n");
fprintf(out, "\tJMP\tRRNZ, L%d_%s_%d\n", function_num, name, loop);
}
//-----------------------------------------------------------------------------
void Backend::branch_false(const char * name, int loop, int size)
{
fprintf(out, ";--\tbranch_false\n");
fprintf(out, "\tJMP\tRRZ, L%d_%s_%d\n", function_num, name, loop);
}
//-----------------------------------------------------------------------------
void Backend::branch_case(const char * name, int loop, int size, int value)
{
int bits = check_size(size, "branch_case");
 
fprintf(out, ";--\tbranch_case (%d bit)\n", bits);
fprintf(out, "\tSEQ\tLL, #0x%4.4X\n", value & 0xFFFF);
fprintf(out, "\tJMP\tRRNZ, L%d_%s_%d_%4.4X\n",
function_num, name, loop, value & 0xFFFF);
}
//-----------------------------------------------------------------------------
void Backend::compute_unary(int what, const char * pretty)
{
const char * opc = "???";
 
fprintf(out, ";--\t16 bit %s\n", pretty);
switch(what)
{
case ET_LOG_NOT: opc = "LNOT"; break;
case ET_NEGATE: opc = "NEG"; break;
case ET_COMPLEMENT: opc = "NOT"; break;
 
default:
assert(0 && "Bad unary what");
break;
}
fprintf(out, "\t%s\tRR\n", opc);
}
//-----------------------------------------------------------------------------
// constant right side (non-constant operand in RR !)
//
void Backend::compute_binary(int what, bool uns, const char * pretty, int value)
{
const char * opc = "???";
 
fprintf(out, ";--\t%s\n", pretty);
switch(what)
{
case ET_BIT_OR: opc = "OR"; break;
case ET_BIT_AND: opc = "AND"; break;
case ET_BIT_XOR: opc = "XOR"; break;
case ET_LEFT: opc = "LSL"; break;
case ET_EQUAL: opc = "SEQ"; break;
case ET_NOT_EQUAL: opc = "SNE"; break;
case ET_LESS_EQUAL: opc = uns ? "SLS" : "SLE"; break;
case ET_LESS: opc = uns ? "SLO" : "SLT"; break;
case ET_GREATER_EQUAL: opc = uns ? "SHS" : "SGE"; break;
case ET_GREATER: opc = uns ? "SHI" : "SGT"; break;
case ET_RIGHT: opc = uns ? "LSR" : "ASR"; break;
 
case ET_ADD: if (value == 0) return;
opc = "ADD";
if (value > 0) break;
opc = "SUB";
value = - value; break;
 
case ET_SUB: if (value == 0) return;
opc = "SUB";
if (value > 0) break;
opc = "ADD";
value = - value; break;
 
 
case ET_MULT: // expr * const
switch(value & 0xFFFF) // special cases
{
case 0x0000: fprintf(out, "\tMOVE\t#0, RR\n");
return;
 
case 0x0001: case 0x0002: case 0x0004: case 0x0008:
case 0x0010: case 0x0020: case 0x0040: case 0x0080:
case 0x0100: case 0x0200: case 0x0400: case 0x0800:
case 0x1000: case 0x2000: case 0x4000:
mult_shift(value, false);
return;
 
case 0xFFFF: case 0xFFFE: case 0xFFFC: case 0xFFF8:
case 0xFFF0: case 0xFFE0: case 0xFFC0: case 0xFF80:
case 0xFF00: case 0xFE00: case 0xFC00: case 0xF800:
case 0xF000: case 0xE000: case 0xC000: case 0x8000:
mult_shift(-value, true);
return;
}
 
fprintf(out, "\tMOVE\tRR, LL\n");
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", value & 0xFFFF);
compute_binary(what, uns, pretty);
return;
 
case ET_DIV: // expr / const
switch(value & 0xFFFF) // special cases
{
case 0x0000: assert(0 && "Division by 0");
 
case 0x0001: case 0x0002: case 0x0004: case 0x0008:
case 0x0010: case 0x0020: case 0x0040: case 0x0080:
case 0x0100: case 0x0200: case 0x0400: case 0x0800:
case 0x1000: case 0x2000: case 0x4000:
div_shift(value, false, uns);
return;
 
case 0xFFFF: case 0xFFFE: case 0xFFFC: case 0xFFF8:
case 0xFFF0: case 0xFFE0: case 0xFFC0: case 0xFF80:
case 0xFF00: case 0xFE00: case 0xFC00: case 0xF800:
case 0xF000: case 0xE000: case 0xC000: case 0x8000:
div_shift(-value, true, uns);
return;
}
 
fprintf(out, "\tMOVE\tRR, LL\n");
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", value & 0xFFFF);
compute_binary(what, uns, pretty);
return;
 
case ET_MOD: // expr % const
switch(value & 0xFFFF) // special cases
{
case 0x0000: assert(0 && "Division by 0");
 
case 0x0001: case 0x0002: case 0x0004: case 0x0008:
case 0x0010: case 0x0020: case 0x0040: case 0x0080:
case 0x0100: case 0x0200: case 0x0400: case 0x0800:
case 0x1000: case 0x2000: case 0x4000:
mod_and(value, false, uns);
return;
 
case 0xFFFF: case 0xFFFE: case 0xFFFC: case 0xFFF8:
case 0xFFF0: case 0xFFE0: case 0xFFC0: case 0xFF80:
case 0xFF00: case 0xFE00: case 0xFC00: case 0xF800:
case 0xF000: case 0xE000: case 0xC000: case 0x8000:
mod_and(-value, true, uns);
return;
}
 
fprintf(out, "\tMOVE\tRR, LL\n");
fprintf(out, "\tMOVE\t#0x%4.4X, RR\n", value & 0xFFFF);
compute_binary(what, uns, pretty);
return;
 
default:
assert(0 && "Bad what");
return;
}
 
fprintf(out, "\t%s\tRR, #0x%4.4X\n", opc, value & 0xFFFF);
}
//-----------------------------------------------------------------------------
void Backend::mult_shift(int value, bool negative)
{
assert(value >= 0);
if (negative) fprintf(out, "\tNEG\tRR\n");
 
switch(value) // special cases
{
case 0x0001: return;
case 0x0002: fprintf(out, "\tLSL\tRR, #1\n"); return;
case 0x0004: fprintf(out, "\tLSL\tRR, #2\n"); return;
case 0x0008: fprintf(out, "\tLSL\tRR, #3\n"); return;
case 0x0010: fprintf(out, "\tLSL\tRR, #4\n"); return;
case 0x0020: fprintf(out, "\tLSL\tRR, #5\n"); return;
case 0x0040: fprintf(out, "\tLSL\tRR, #6\n"); return;
case 0x0080: fprintf(out, "\tLSL\tRR, #7\n"); return;
case 0x0100: fprintf(out, "\tLSL\tRR, #8\n"); return;
case 0x0200: fprintf(out, "\tLSL\tRR, #9\n"); return;
case 0x0400: fprintf(out, "\tLSL\tRR, #10\n"); return;
case 0x0800: fprintf(out, "\tLSL\tRR, #11\n"); return;
case 0x1000: fprintf(out, "\tLSL\tRR, #12\n"); return;
case 0x2000: fprintf(out, "\tLSL\tRR, #13\n"); return;
case 0x4000: fprintf(out, "\tLSL\tRR, #14\n"); return;
case 0x8000: fprintf(out, "\tLSL\tRR, #15\n"); return;
default: assert(0);
}
}
//-----------------------------------------------------------------------------
void Backend::div_shift(int value, bool negative, bool uns)
{
assert(value >= 0);
if (negative) fprintf(out, "\tNEG\tRR\n");
 
const char * op = "ASR";
if (uns) op = "LSR";
 
switch(value) // special cases
{
case 0x0001: return;
case 0x0002: fprintf(out, "\t%s\tRR, #1\n", op); return;
case 0x0004: fprintf(out, "\t%s\tRR, #2\n", op); return;
case 0x0008: fprintf(out, "\t%s\tRR, #3\n", op); return;
case 0x0010: fprintf(out, "\t%s\tRR, #4\n", op); return;
case 0x0020: fprintf(out, "\t%s\tRR, #5\n", op); return;
case 0x0040: fprintf(out, "\t%s\tRR, #6\n", op); return;
case 0x0080: fprintf(out, "\t%s\tRR, #7\n", op); return;
case 0x0100: fprintf(out, "\t%s\tRR, #8\n", op); return;
case 0x0200: fprintf(out, "\t%s\tRR, #9\n", op); return;
case 0x0400: fprintf(out, "\t%s\tRR, #10\n", op); return;
case 0x0800: fprintf(out, "\t%s\tRR, #11\n", op); return;
case 0x1000: fprintf(out, "\t%s\tRR, #12\n", op); return;
case 0x2000: fprintf(out, "\t%s\tRR, #13\n", op); return;
case 0x4000: fprintf(out, "\t%s\tRR, #14\n", op); return;
case 0x8000: fprintf(out, "\t%s\tRR, #15\n", op); return;
default: assert(0);
}
}
//-----------------------------------------------------------------------------
void Backend::mod_and(int value, bool negative, bool uns)
{
assert(value >= 0);
if (negative) fprintf(out, "\tNEG\tRR\n");
 
switch(value) // special cases
{
case 0x0001: fprintf(out, "\tMOVE\t#0, RR\n"); return;
case 0x0002: fprintf(out, "\tAND\tRR, #0x0001\n"); return;
case 0x0004: fprintf(out, "\tAND\tRR, #0x0003\n"); return;
case 0x0008: fprintf(out, "\tAND\tRR, #0x0007\n"); return;
case 0x0010: fprintf(out, "\tAND\tRR, #0x000F\n"); return;
case 0x0020: fprintf(out, "\tAND\tRR, #0x001F\n"); return;
case 0x0040: fprintf(out, "\tAND\tRR, #0x003F\n"); return;
case 0x0080: fprintf(out, "\tAND\tRR, #0x007F\n"); return;
case 0x0100: fprintf(out, "\tAND\tRR, #0x00FF\n"); return;
case 0x0200: fprintf(out, "\tAND\tRR, #0x01FF\n"); return;
case 0x0400: fprintf(out, "\tAND\tRR, #0x03FF\n"); return;
case 0x0800: fprintf(out, "\tAND\tRR, #0x07FF\n"); return;
case 0x1000: fprintf(out, "\tAND\tRR, #0x0FFF\n"); return;
case 0x2000: fprintf(out, "\tAND\tRR, #0x1FFF\n"); return;
case 0x4000: fprintf(out, "\tAND\tRR, #0x3FFF\n"); return;
case 0x8000: fprintf(out, "\tAND\tRR, #0x7FFF\n"); return;
default: assert(0);
}
}
//-----------------------------------------------------------------------------
// constant left side (non-constant operand in RR !)
//
void Backend::compute_binary(int what, bool uns, int value, const char * pretty)
{
// symmetric operators: exchange left and right...
//
switch(what)
{
case ET_BIT_OR:
case ET_BIT_AND:
case ET_BIT_XOR:
case ET_ADD:
case ET_MULT:
case ET_EQUAL:
case ET_NOT_EQUAL:
compute_binary(what, uns, pretty, value); return;
 
case ET_LESS_EQUAL:
compute_binary(ET_GREATER, uns, ">", value); return;
 
case ET_LESS:
compute_binary(ET_GREATER_EQUAL, uns, ">=", value); return;
 
case ET_GREATER_EQUAL:
compute_binary(ET_LESS, uns, "<", value); return;
 
case ET_GREATER:
compute_binary(ET_LESS_EQUAL, uns, "<=", value); return;
}
 
// assymmetric operators: load constant and call non-const operator
//
switch(what)
{
case ET_SUB:
case ET_LEFT:
case ET_RIGHT:
case ET_DIV:
case ET_MOD:
fprintf(out, "\tMOVE\t#0x%4.4X, LL\n", value & 0xFFFF);
compute_binary(what, uns, pretty);
return;
}
 
assert(0 && "Bad what");
}
//-----------------------------------------------------------------------------
void Backend::compute_binary(int what, bool uns, const char * pretty)
{
const char * opc = "???";
 
fprintf(out, ";--\t%s\n", pretty);
switch(what)
{
case ET_BIT_OR: opc = "OR"; break;
case ET_BIT_AND: opc = "AND"; break;
case ET_BIT_XOR: opc = "XOR"; break;
case ET_ADD: opc = "ADD"; break;
case ET_SUB: opc = "SUB"; break;
case ET_EQUAL: opc = "SEQ"; break;
case ET_NOT_EQUAL: opc = "SNE"; break;
case ET_LESS_EQUAL: opc = uns ? "SLS" : "SLE"; break;
case ET_LESS: opc = uns ? "SLO" : "SLT"; break;
case ET_GREATER_EQUAL: opc = uns ? "SHS" : "SGE"; break;
case ET_GREATER: opc = uns ? "SHI" : "SGT"; break;
 
case ET_MULT: // expr * expr
fprintf(out, "\tDI\n");
if (uns) fprintf(out, "\tMUL_IU\n");
else fprintf(out, "\tMUL_IS\n");
fprintf(out, "\tCALL\tmult_div\n");
fprintf(out, "\tMD_FIN\n");
fprintf(out, "\tEI\n");
return;
 
case ET_DIV: // expr / expr
fprintf(out, "\tDI\n");
if (uns) fprintf(out, "\tDIV_IU\n");
else fprintf(out, "\tDIV_IS\n");
fprintf(out, "\tCALL\tmult_div\n");
fprintf(out, "\tMD_FIN\n");
fprintf(out, "\tEI\n");
return;
 
case ET_MOD: // expr % expr
fprintf(out, "\tDI\n");
if (uns) fprintf(out, "\tDIV_IU\n");
else fprintf(out, "\tDIV_IS\n");
fprintf(out, "\tCALL\tmult_div\n");
fprintf(out, "\tMOD_FIN\n");
fprintf(out, "\tEI\n");
return;
 
default:
assert(0 && "Bad what");
break;
}
 
fprintf(out, "\t%s\tLL, RR\n", opc);
}
//-----------------------------------------------------------------------------
void Backend::content(SUW suw)
{
check_size(suw, "content");
fprintf(out, ";--\tcontent\n");
if (suw == SB) fprintf(out, "\tMOVE\t(RR), RS\n");
else if (suw == UB) fprintf(out, "\tMOVE\t(RR), RU\n");
else fprintf(out, "\tMOVE\t(RR), RR\n");
}
//-----------------------------------------------------------------------------
void Backend::scale_rr(int size)
{
assert(size > 0);
fprintf(out, ";--\tscale_rr *%d\n", size);
 
if (size == 1) return;
check_size(size, "scale_rr");
 
compute_binary(ET_MULT, false, "*", size);
// fprintf(out, "\tLSL\tRR, #%d\n", size);
}
//-----------------------------------------------------------------------------
void Backend::unscale_rr(int size, bool uns)
{
assert(size > 0);
fprintf(out, ";--\tscale *%d\n", size);
 
if (size == 1) return;
check_size(size, "unscale_rr");
 
compute_binary(ET_DIV, uns, "/", size);
// if (uns) fprintf(out, "\tLSR\tRR, #%d\n", size);
// else fprintf(out, "\tASR\tRR, #%d\n", size);
}
//-----------------------------------------------------------------------------
/Makefile~
0,0 → 1,37
 
ZAS := C:/sdcc/bin/as-z80
ZLD := C:/sdcc/bin/aslink
 
HDR := ansic_bison.cc.h Node.hh Backend.hh Name.hh
OBJ := cc80.o ansic_bison.o ansic_flex.o Node.o Name.o Expression.o \
Statement.o Backend.o
MEMTOP := 0x2000
 
all: test
 
cc80.exe: $(OBJ)
gcc -g -o $@ $(OBJ)
 
%.o: %.cc $(HDR)
gcc -g -c -o $@ $<
 
ansic_bison.cc: ansic.bison
bison -d -v -o $@ $<
 
ansic_bison.cc.h: ansic.bison
bison -d -v -o ansi_bison.cc $<
 
ansic_flex.cc: ansic.flex ansic_bison.cc.h
flex -o$@ $<
 
loader: cc80.exe
cc80 -l ..\loader.c ..\loader.asm
 
test: cc80.exe
cc80 ..\test.c ..\test.asm
 
rtos: cc80.exe
cc80 ..\rtos.c ..\rtos.asm
 
clean:
 
/Makefile
0,0 → 1,37
 
ZAS := C:/sdcc/bin/as-z80
ZLD := C:/sdcc/bin/aslink
 
HDR := ansic_bison.cc.h Node.hh Backend.hh Name.hh
OBJ := cc80.o ansic_bison.o ansic_flex.o Node.o Name.o Expression.o \
Statement.o Backend.o
MEMTOP := 0x2000
 
all: test
 
cc80.exe: $(OBJ)
gcc -g -o $@ $(OBJ)
 
%.o: %.cc $(HDR)
gcc -g -c -o $@ $<
 
ansic_bison.cc: ansic.bison
bison -d -v -o $@ $<
 
ansic_bison.cc.h: ansic.bison
bison -d -v -o ansi_bison.cc $<
 
ansic_flex.cc: ansic.flex ansic_bison.cc.h
flex -o$@ $<
 
loader: cc80.exe
cc80 -l $(MEMTOP) ..\loader.c ..\loader.asm
 
test: cc80.exe
cc80 $(MEMTOP) ..\test.c ..\test.asm
 
rtos: cc80.exe
cc80 $(MEMTOP) ..\rtos.c ..\rtos.asm
 
clean:
 
/cc80.exe Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
cc80.exe Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: Name.hh =================================================================== --- Name.hh (nonexistent) +++ Name.hh (revision 26) @@ -0,0 +1,88 @@ +// Name.hh + +#include "List.hh" +class TypeName; + +//----------------------------------------------------------------------------- +class Name +{ +public: + Name(const char * n, Name * t, TypeName * d, int spos) + : name(n), + tail(t), + decl(d), + stack_position(spos) + {} + + static TypeName * FindType(const char * na); + static int FindPos(const char * na); + static bool FindEnum(const char * na, int & value); + static void AddExtern(const char * na, TypeName * decl); + static void AddStatic(const char * na, TypeName * decl); + static void AddEnum(const char * na, int value); + static void AddLocal(const char * na, TypeName * decl); + static void AddAuto(const char * na, TypeName * decl, int spos = 0); + static void SetAutoPos(const char * na, int spos); + static void RemoveAuto(); + static void AutoToLocal(); + static void PrintAll(FILE * out); + + void Print(FILE * out); + +private: + const char * name; + Name * tail; + TypeName * decl; + int stack_position; + + static Name * FindDeclared(const char * na); + + static Name * externs; + static Name * statics; + static Name * locals; + static Name * enums; + static Name * autos; +}; +//----------------------------------------------------------------------------- +class TypedefName +{ +public: + TypedefName(const char * n, TypedefName * t, TypeName * d) + : name(n), + tail(t), + decl(d) + {} + + static bool IsDefined(const char * na); + static TypeName * Find(const char * na); + static void Add(const char * na, TypeName * decl); + +private: + const char * name; + TypedefName * tail; + TypeName * decl; + + static TypedefName * typedefs; +}; +//----------------------------------------------------------------------------- +class StructName +{ +public: + StructName(const char * n, StructName * t, StructDeclarationList * sdl) + : name(n), + tail(t), + sdlist(sdl) + {} + + static bool IsDefined(const char * na); + static StructDeclarationList * Find(const char * na); + static void Add(const char * na, StructDeclarationList * sdl); + +private: + const char * name; + StructName * tail; + StructDeclarationList * sdlist; + + static StructName * structs; +}; +//-----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.