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;
+};
+//-----------------------------------------------------------------------------