// Expression.cc
|
// Expression.cc
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <assert.h>
|
#include <assert.h>
|
#include "Node.hh"
|
#include "Node.hh"
|
#include "Name.hh"
|
#include "Name.hh"
|
#include "Backend.hh"
|
#include "Backend.hh"
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * NumericExpression::OptNegate()
|
Expression * NumericExpression::OptNegate()
|
{
|
{
|
int_value->Negate();
|
int_value->Negate();
|
return this;
|
return this;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * NumericExpression::OptComplement()
|
Expression * NumericExpression::OptComplement()
|
{
|
{
|
int_value->Complement();
|
int_value->Complement();
|
return this;
|
return this;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * NumericExpression::OptLogNot()
|
Expression * NumericExpression::OptLogNot()
|
{
|
{
|
int_value->LogNot();
|
int_value->LogNot();
|
return this;
|
return this;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * NumericExpression::SetType()
|
TypeName * NumericExpression::SetType()
|
{
|
{
|
assert(int_value);
|
assert(int_value);
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void NumericExpression::EmitInitialization(FILE * out, int size)
|
void NumericExpression::EmitInitialization(FILE * out, int size)
|
{
|
{
|
const int value = int_value->GetValue();
|
const int value = int_value->GetValue();
|
assert(int_value);
|
assert(int_value);
|
if (size == 1) fprintf(out, "\t.BYTE\t%d\n", 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 if (size == 2) fprintf(out, "\t.WORD\t%d\n", value);
|
else assert(0 && "Bad size");
|
else assert(0 && "Bad size");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
NumericExpression::NumericExpression(TypeName * t)
|
NumericExpression::NumericExpression(TypeName * t)
|
: Expression("NumericExpression (sizeof type)")
|
: Expression("NumericExpression (sizeof type)")
|
{
|
{
|
assert(t);
|
assert(t);
|
int_value = new NumericConstant(t->GetSize());
|
int_value = new NumericConstant(t->GetSize());
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
NumericExpression::NumericExpression(Expression * r)
|
NumericExpression::NumericExpression(Expression * r)
|
: Expression("NumericExpression (sizeof expr)"),
|
: Expression("NumericExpression (sizeof expr)"),
|
int_value(0)
|
int_value(0)
|
{
|
{
|
assert(r);
|
assert(r);
|
|
|
int_value = new NumericConstant(r->GetSize());
|
int_value = new NumericConstant(r->GetSize());
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * NumericExpression::GetPretty(int val)
|
const char * NumericExpression::GetPretty(int val)
|
{
|
{
|
char * cp = new char[50];
|
char * cp = new char[50];
|
assert(cp);
|
assert(cp);
|
sprintf(cp, "NumericExpression (constant %d = 0x%X)", val, val);
|
sprintf(cp, "NumericExpression (constant %d = 0x%X)", val, val);
|
return cp;
|
return cp;
|
|
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
NumericExpression::NumericExpression(NumericConstant * n)
|
NumericExpression::NumericExpression(NumericConstant * n)
|
: Expression(GetPretty(n->GetValue())),
|
: Expression(GetPretty(n->GetValue())),
|
int_value(n)
|
int_value(n)
|
{
|
{
|
assert(n);
|
assert(n);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
NumericExpression::NumericExpression(int value)
|
NumericExpression::NumericExpression(int value)
|
: Expression(GetPretty(value)),
|
: Expression(GetPretty(value)),
|
int_value(0)
|
int_value(0)
|
{
|
{
|
int_value = new NumericConstant(value);
|
int_value = new NumericConstant(value);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
StringExpression::StringExpression(StringConstant * s)
|
StringExpression::StringExpression(StringConstant * s)
|
: Expression("StringExpression"),
|
: Expression("StringExpression"),
|
string_constant(s)
|
string_constant(s)
|
{
|
{
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * StringExpression::SetType()
|
TypeName * StringExpression::SetType()
|
{
|
{
|
/*
|
/*
|
TypeSpecifier * con = new TypeSpecifier(TQ_CONST);
|
TypeSpecifier * con = new TypeSpecifier(TQ_CONST);
|
Ptr * ptr = new Ptr(con);
|
Ptr * ptr = new Ptr(con);
|
Pointer * pointer = new Pointer(ptr, 0);
|
Pointer * pointer = new Pointer(ptr, 0);
|
DeclItem * di = new DeclItem(pointer);
|
DeclItem * di = new DeclItem(pointer);
|
Declarator * decl = new Declarator(di, 0);
|
Declarator * decl = new Declarator(di, 0);
|
TypeSpecifier * ts = new TypeSpecifier(TS_CHAR);
|
TypeSpecifier * ts = new TypeSpecifier(TS_CHAR);
|
*/
|
*/
|
|
|
char * name = new char[10];
|
char * name = new char[10];
|
assert(string_constant);
|
assert(string_constant);
|
sprintf(name, "Cstr_%d", string_constant->GetStringNumber());
|
sprintf(name, "Cstr_%d", string_constant->GetStringNumber());
|
|
|
const int len = string_constant->GetLength() + 1; // 1 for terminatin 0
|
const int len = string_constant->GetLength() + 1; // 1 for terminatin 0
|
Expression * lex = new NumericExpression(len);
|
Expression * lex = new NumericExpression(len);
|
|
|
TypeSpecifier * ts = new TypeSpecifier(TS_CHAR);
|
TypeSpecifier * ts = new TypeSpecifier(TS_CHAR);
|
|
|
DeclItem * na_it = new DeclItem(name);
|
DeclItem * na_it = new DeclItem(name);
|
DeclItem * ar_it = new DeclItem(lex);
|
DeclItem * ar_it = new DeclItem(lex);
|
|
|
Declarator * ar_dcl = new Declarator(ar_it, 0);
|
Declarator * ar_dcl = new Declarator(ar_it, 0);
|
Declarator * na_dcl = new Declarator(na_it, ar_dcl);
|
Declarator * na_dcl = new Declarator(na_it, ar_dcl);
|
return new TypeName(ts, na_dcl);
|
return new TypeName(ts, na_dcl);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StringExpression::EmitInitialization(FILE * out, int size)
|
void StringExpression::EmitInitialization(FILE * out, int size)
|
{
|
{
|
assert(string_constant);
|
assert(string_constant);
|
assert(size == 2);
|
assert(size == 2);
|
fprintf(out, "\t.WORD\tCstr_%d\n", string_constant->GetStringNumber());
|
fprintf(out, "\t.WORD\tCstr_%d\n", string_constant->GetStringNumber());
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * IdentifierExpression::SetType()
|
TypeName * IdentifierExpression::SetType()
|
{
|
{
|
assert(varname);
|
assert(varname);
|
TypeName * ret = Name::FindType(varname);
|
TypeName * ret = Name::FindType(varname);
|
|
|
if (ret) return ret;
|
if (ret) return ret;
|
|
|
fprintf(stderr, "Symbol '%s' not declared\n", varname);
|
fprintf(stderr, "Symbol '%s' not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
MemberExpression::MemberExpression(bool is_pointer, Expression * l,
|
MemberExpression::MemberExpression(bool is_pointer, Expression * l,
|
const char * s)
|
const char * s)
|
: Expression("Expression l.member"),
|
: Expression("Expression l.member"),
|
membername(s),
|
membername(s),
|
left(l)
|
left(l)
|
{
|
{
|
if (is_pointer) // map l->s to (*l).s
|
if (is_pointer) // map l->s to (*l).s
|
{
|
{
|
left = UnaryExpression::New(ET_CONTENT, left);
|
left = UnaryExpression::New(ET_CONTENT, left);
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * MemberExpression::SetType()
|
TypeName * MemberExpression::SetType()
|
{
|
{
|
assert(left);
|
assert(left);
|
return left->GetType()->GetMemberType(membername);
|
return left->GetType()->GetMemberType(membername);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void MemberExpression::Emit(FILE * out)
|
void MemberExpression::Emit(FILE * out)
|
{
|
{
|
EmitAddress(out, true);
|
EmitAddress(out, true);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void MemberExpression::EmitAddress(FILE * out)
|
void MemberExpression::EmitAddress(FILE * out)
|
{
|
{
|
EmitAddress(out, false);
|
EmitAddress(out, false);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void MemberExpression::EmitAddress(FILE * out, bool content)
|
void MemberExpression::EmitAddress(FILE * out, bool content)
|
{
|
{
|
assert(membername);
|
assert(membername);
|
|
|
TypeName * struct_type = left->GetType();
|
TypeName * struct_type = left->GetType();
|
assert(struct_type);
|
assert(struct_type);
|
|
|
if (!struct_type->IsStruct())
|
if (!struct_type->IsStruct())
|
{
|
{
|
fprintf(stderr, "request for member %s of non-struct\n", membername);
|
fprintf(stderr, "request for member %s of non-struct\n", membername);
|
semantic_errors++;
|
semantic_errors++;
|
}
|
}
|
|
|
TypeSpecifier * ts = struct_type->GetTypeSpecifier();
|
TypeSpecifier * ts = struct_type->GetTypeSpecifier();
|
assert(ts);
|
assert(ts);
|
|
|
const char * sname = ts->GetName();
|
const char * sname = ts->GetName();
|
if (sname == 0)
|
if (sname == 0)
|
{
|
{
|
fprintf(stderr, "No struct name in member expression\n");
|
fprintf(stderr, "No struct name in member expression\n");
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
StructDeclarationList * sdl = StructName::Find(sname);
|
StructDeclarationList * sdl = StructName::Find(sname);
|
if (sdl == 0)
|
if (sdl == 0)
|
{
|
{
|
fprintf(stderr, "No struct %s defined\n", sname);
|
fprintf(stderr, "No struct %s defined\n", sname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
int position = -1;
|
int position = -1;
|
TypeName * membtype = 0;
|
TypeName * membtype = 0;
|
|
|
for (; sdl; sdl = sdl->Tail())
|
for (; sdl; sdl = sdl->Tail())
|
{
|
{
|
StructDeclaration * sd = sdl->Head();
|
StructDeclaration * sd = sdl->Head();
|
assert(sd);
|
assert(sd);
|
position = sd->GetMemberPosition(sname, membername, ts->IsUnion());
|
position = sd->GetMemberPosition(sname, membername, ts->IsUnion());
|
if (position == -1) continue;
|
if (position == -1) continue;
|
|
|
membtype = sd->GetMemberType(sname, membername);
|
membtype = sd->GetMemberType(sname, membername);
|
assert(membtype);
|
assert(membtype);
|
break;
|
break;
|
}
|
}
|
|
|
if (!membtype)
|
if (!membtype)
|
{
|
{
|
fprintf(stderr, "struct %s has no member %s\n", sname, membername);
|
fprintf(stderr, "struct %s has no member %s\n", sname, membername);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
left->EmitAddress(out);
|
left->EmitAddress(out);
|
Backend::compute_binary(ET_ADD, true, position, "+ (member)");
|
Backend::compute_binary(ET_ADD, true, position, "+ (member)");
|
if (content) Backend::content(membtype->GetSUW());
|
if (content) Backend::content(membtype->GetSUW());
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * UnaryExpression::New(UnaExprType et, Expression * r)
|
Expression * UnaryExpression::New(UnaExprType et, Expression * r)
|
{
|
{
|
assert(r);
|
assert(r);
|
|
|
if (r->IsConstant())
|
if (r->IsConstant())
|
{
|
{
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_CONJUGATE: return r;
|
case ET_CONJUGATE: return r;
|
case ET_NEGATE: return r->OptNegate();
|
case ET_NEGATE: return r->OptNegate();
|
case ET_COMPLEMENT: return r->OptComplement();
|
case ET_COMPLEMENT: return r->OptComplement();
|
case ET_LOG_NOT: return r->OptLogNot();
|
case ET_LOG_NOT: return r->OptLogNot();
|
}
|
}
|
}
|
}
|
|
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_POSTINC: // x++ = ++x - 1
|
case ET_POSTINC: // x++ = ++x - 1
|
{
|
{
|
Expression * pre = UnaryExpression::New(ET_PREINC, r);
|
Expression * pre = UnaryExpression::New(ET_PREINC, r);
|
NumericConstant * num = new NumericConstant(1);
|
NumericConstant * num = new NumericConstant(1);
|
NumericExpression * one = new NumericExpression(num);
|
NumericExpression * one = new NumericExpression(num);
|
return SubtractionExpression::New(pre, one);
|
return SubtractionExpression::New(pre, one);
|
}
|
}
|
|
|
case ET_POSTDEC: // x-- = --x + 1
|
case ET_POSTDEC: // x-- = --x + 1
|
{
|
{
|
Expression * pre = UnaryExpression::New(ET_PREDEC, r);
|
Expression * pre = UnaryExpression::New(ET_PREDEC, r);
|
NumericConstant * num = new NumericConstant(1);
|
NumericConstant * num = new NumericConstant(1);
|
NumericExpression * one = new NumericExpression(num);
|
NumericExpression * one = new NumericExpression(num);
|
return AdditionExpression::New(pre, one);
|
return AdditionExpression::New(pre, one);
|
}
|
}
|
}
|
}
|
|
|
return new UnaryExpression(et, r);
|
return new UnaryExpression(et, r);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * UnaryExpression::SetType()
|
TypeName * UnaryExpression::SetType()
|
{
|
{
|
assert(right);
|
assert(right);
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_CONJUGATE:
|
case ET_CONJUGATE:
|
case ET_NEGATE:
|
case ET_NEGATE:
|
case ET_COMPLEMENT:
|
case ET_COMPLEMENT:
|
case ET_PREINC:
|
case ET_PREINC:
|
case ET_PREDEC:
|
case ET_PREDEC:
|
case ET_POSTINC:
|
case ET_POSTINC:
|
case ET_POSTDEC:
|
case ET_POSTDEC:
|
return right->GetType();
|
return right->GetType();
|
|
|
case ET_LOG_NOT:
|
case ET_LOG_NOT:
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
|
|
case ET_ADDRESS:
|
case ET_ADDRESS:
|
return right->GetType()->AddressOf();
|
return right->GetType()->AddressOf();
|
|
|
case ET_CONTENT:
|
case ET_CONTENT:
|
return right->GetType()->ContentOf();
|
return right->GetType()->ContentOf();
|
|
|
default: assert(0 && "Bad unary operator");
|
default: assert(0 && "Bad unary operator");
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
UnaryExpression::UnaryExpression(TypeName * t, Expression * r)
|
UnaryExpression::UnaryExpression(TypeName * t, Expression * r)
|
: Expression("Expression (cast)r"),
|
: Expression("Expression (cast)r"),
|
expr_type(ET_CAST),
|
expr_type(ET_CAST),
|
right(r)
|
right(r)
|
{
|
{
|
assert(right);
|
assert(right);
|
Expression::SetType(t);
|
Expression::SetType(t);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * AdditionExpression::New(Expression * l, Expression * r)
|
Expression * AdditionExpression::New(Expression * l, Expression * r)
|
{
|
{
|
if (l->IsVariable() && l->IsArray())
|
if (l->IsVariable() && l->IsArray())
|
{
|
{
|
l = UnaryExpression::New(ET_ADDRESS, l);
|
l = UnaryExpression::New(ET_ADDRESS, l);
|
}
|
}
|
|
|
if (r->IsVariable() && r->IsArray())
|
if (r->IsVariable() && r->IsArray())
|
{
|
{
|
r = UnaryExpression::New(ET_ADDRESS, r);
|
r = UnaryExpression::New(ET_ADDRESS, r);
|
}
|
}
|
|
|
if (l->IsNumericConstant() && r->IsNumericConstant())
|
if (l->IsNumericConstant() && r->IsNumericConstant())
|
{
|
{
|
const int lval = l->GetConstantNumericValue();
|
const int lval = l->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval + rval);
|
return new NumericExpression(lval + rval);
|
}
|
}
|
|
|
return new AdditionExpression(l, r);
|
return new AdditionExpression(l, r);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * SubtractionExpression::New(Expression * l, Expression * r)
|
Expression * SubtractionExpression::New(Expression * l, Expression * r)
|
{
|
{
|
if (l->IsNumericConstant() && r->IsNumericConstant())
|
if (l->IsNumericConstant() && r->IsNumericConstant())
|
{
|
{
|
const int lval = l->GetConstantNumericValue();
|
const int lval = l->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval - rval);
|
return new NumericExpression(lval - rval);
|
}
|
}
|
|
|
return new SubtractionExpression(l, r);
|
return new SubtractionExpression(l, r);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * BinaryExpression::New(BinExprType et, Expression * l,
|
Expression * BinaryExpression::New(BinExprType et, Expression * l,
|
Expression * r)
|
Expression * r)
|
{
|
{
|
assert(l);
|
assert(l);
|
if (!r) return new BinaryExpression(et, l, r); // function call
|
if (!r) return new BinaryExpression(et, l, r); // function call
|
|
|
if (l->IsNumericConstant() && r->IsNumericConstant())
|
if (l->IsNumericConstant() && r->IsNumericConstant())
|
{
|
{
|
const int lval = l->GetConstantNumericValue();
|
const int lval = l->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_LIST:
|
case ET_LIST:
|
delete l;
|
delete l;
|
return r;
|
return r;
|
|
|
case ET_BIT_OR:
|
case ET_BIT_OR:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval | rval);
|
return new NumericExpression(lval | rval);
|
|
|
case ET_BIT_AND:
|
case ET_BIT_AND:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval & rval);
|
return new NumericExpression(lval & rval);
|
|
|
case ET_BIT_XOR:
|
case ET_BIT_XOR:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval ^ rval);
|
return new NumericExpression(lval ^ rval);
|
|
|
case ET_LOG_OR:
|
case ET_LOG_OR:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval || rval) return new NumericExpression(-1);
|
if (lval || rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_LOG_AND:
|
case ET_LOG_AND:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval || rval) return new NumericExpression(-1);
|
if (lval || rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_EQUAL:
|
case ET_EQUAL:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval == rval) return new NumericExpression(-1);
|
if (lval == rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_NOT_EQUAL:
|
case ET_NOT_EQUAL:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval != rval) return new NumericExpression(-1);
|
if (lval != rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_LESS_EQUAL:
|
case ET_LESS_EQUAL:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval <= rval) return new NumericExpression(-1);
|
if (lval <= rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_LESS:
|
case ET_LESS:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval < rval) return new NumericExpression(-1);
|
if (lval < rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_GREATER_EQUAL:
|
case ET_GREATER_EQUAL:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval >= rval) return new NumericExpression(-1);
|
if (lval >= rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_GREATER:
|
case ET_GREATER:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
if (lval > rval) return new NumericExpression(-1);
|
if (lval > rval) return new NumericExpression(-1);
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
|
|
case ET_LEFT:
|
case ET_LEFT:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval << rval);
|
return new NumericExpression(lval << rval);
|
|
|
case ET_RIGHT:
|
case ET_RIGHT:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval >> rval);
|
return new NumericExpression(lval >> rval);
|
|
|
case ET_MULT:
|
case ET_MULT:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(lval * rval);
|
return new NumericExpression(lval * rval);
|
|
|
case ET_DIV:
|
case ET_DIV:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
assert(rval);
|
assert(rval);
|
return new NumericExpression(lval / rval);
|
return new NumericExpression(lval / rval);
|
|
|
case ET_MOD:
|
case ET_MOD:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
assert(rval);
|
assert(rval);
|
return new NumericExpression(lval % rval);
|
return new NumericExpression(lval % rval);
|
}
|
}
|
}
|
}
|
|
|
if (l->IsNumericConstant())
|
if (l->IsNumericConstant())
|
{
|
{
|
const int lval = l->GetConstantNumericValue();
|
const int lval = l->GetConstantNumericValue();
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_LIST:
|
case ET_LIST:
|
delete l;
|
delete l;
|
return r;
|
return r;
|
|
|
case ET_LOG_OR:
|
case ET_LOG_OR:
|
delete l;
|
delete l;
|
if (lval == 0) return r;
|
if (lval == 0) return r;
|
delete r;
|
delete r;
|
return new NumericExpression(-1);
|
return new NumericExpression(-1);
|
|
|
case ET_LOG_AND:
|
case ET_LOG_AND:
|
delete l;
|
delete l;
|
if (lval != 0) return r;
|
if (lval != 0) return r;
|
delete r;
|
delete r;
|
return new NumericExpression(0);
|
return new NumericExpression(0);
|
}
|
}
|
}
|
}
|
else if (l->IsConstant()) // otherwise string (pointer) : always nonzero
|
else if (l->IsConstant()) // otherwise string (pointer) : always nonzero
|
{
|
{
|
assert(l->IsStringConstant());
|
assert(l->IsStringConstant());
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_LOG_OR:
|
case ET_LOG_OR:
|
delete l;
|
delete l;
|
delete r;
|
delete r;
|
return new NumericExpression(-1);
|
return new NumericExpression(-1);
|
|
|
case ET_LOG_AND:
|
case ET_LOG_AND:
|
delete l;
|
delete l;
|
return r;
|
return r;
|
|
|
case ET_LIST:
|
case ET_LIST:
|
delete l;
|
delete l;
|
return r;
|
return r;
|
}
|
}
|
}
|
}
|
|
|
if (r->IsNumericConstant())
|
if (r->IsNumericConstant())
|
{
|
{
|
const int rval = r->GetConstantNumericValue();
|
const int rval = r->GetConstantNumericValue();
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_LOG_OR:
|
case ET_LOG_OR:
|
if (!rval) return l;
|
if (!rval) return l;
|
break;
|
break;
|
|
|
case ET_LOG_AND:
|
case ET_LOG_AND:
|
if (rval) return l;
|
if (rval) return l;
|
break;
|
break;
|
|
|
}
|
}
|
}
|
}
|
else if (r->IsConstant()) // otherwise string (pointer) : always nonzero
|
else if (r->IsConstant()) // otherwise string (pointer) : always nonzero
|
{
|
{
|
assert(r->IsStringConstant());
|
assert(r->IsStringConstant());
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_LOG_AND: return r;
|
case ET_LOG_AND: return r;
|
}
|
}
|
}
|
}
|
|
|
return new BinaryExpression(et, l, r);
|
return new BinaryExpression(et, l, r);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
BinaryExpression::BinaryExpression(BinExprType et,
|
BinaryExpression::BinaryExpression(BinExprType et,
|
Expression * l, Expression * r)
|
Expression * l, Expression * r)
|
: Expression(GetPrettyName(GetPretty(et))),
|
: Expression(GetPrettyName(GetPretty(et))),
|
expr_type(et),
|
expr_type(et),
|
left(l),
|
left(l),
|
right(r)
|
right(r)
|
{
|
{
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_ADD_ASSIGN: // expr += expr
|
case ET_ADD_ASSIGN: // expr += expr
|
right = AdditionExpression::New(l, right);
|
right = AdditionExpression::New(l, right);
|
expr_type = ET_ASSIGN;
|
expr_type = ET_ASSIGN;
|
return;
|
return;
|
|
|
case ET_SUB_ASSIGN: // expr -= expr
|
case ET_SUB_ASSIGN: // expr -= expr
|
right = SubtractionExpression::New(l, right);
|
right = SubtractionExpression::New(l, right);
|
expr_type = ET_ASSIGN;
|
expr_type = ET_ASSIGN;
|
return;
|
return;
|
|
|
case ET_MULT_ASSIGN: // expr *= expr
|
case ET_MULT_ASSIGN: // expr *= expr
|
case ET_DIV_ASSIGN: // expr /= expr
|
case ET_DIV_ASSIGN: // expr /= expr
|
case ET_MOD_ASSIGN: // expr %= expr
|
case ET_MOD_ASSIGN: // expr %= expr
|
case ET_LEFT_ASSIGN: // expr <<= expr
|
case ET_LEFT_ASSIGN: // expr <<= expr
|
case ET_RIGHT_ASSIGN: // expr >>= expr
|
case ET_RIGHT_ASSIGN: // expr >>= expr
|
case ET_AND_ASSIGN: // expr &= expr
|
case ET_AND_ASSIGN: // expr &= expr
|
case ET_XOR_ASSIGN: // expr ^= expr
|
case ET_XOR_ASSIGN: // expr ^= expr
|
case ET_OR_ASSIGN: // expr |= expr
|
case ET_OR_ASSIGN: // expr |= expr
|
right = new BinaryExpression(MapAssign(expr_type), l, right);
|
right = new BinaryExpression(MapAssign(expr_type), l, right);
|
expr_type = ET_ASSIGN;
|
expr_type = ET_ASSIGN;
|
return;
|
return;
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * BinaryExpression::SetType()
|
TypeName * BinaryExpression::SetType()
|
{
|
{
|
assert(left);
|
assert(left);
|
assert(right || expr_type == ET_FUNCALL); // zero if no args
|
assert(right || expr_type == ET_FUNCALL); // zero if no args
|
|
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_LIST: // expr , expr
|
case ET_LIST: // expr , expr
|
case ET_LEFT: // expr << expr
|
case ET_LEFT: // expr << expr
|
case ET_RIGHT: // expr >> expr
|
case ET_RIGHT: // expr >> expr
|
return right->GetType();
|
return right->GetType();
|
|
|
case ET_ASSIGN: // expr = expr
|
case ET_ASSIGN: // expr = expr
|
return left->GetType();
|
return left->GetType();
|
|
|
case ET_EQUAL: // expr == expr
|
case ET_EQUAL: // expr == expr
|
case ET_NOT_EQUAL: // expr != expr
|
case ET_NOT_EQUAL: // expr != expr
|
case ET_LESS_EQUAL: // expr <= expr
|
case ET_LESS_EQUAL: // expr <= expr
|
case ET_LESS: // expr < expr
|
case ET_LESS: // expr < expr
|
case ET_GREATER_EQUAL: // expr >= expr
|
case ET_GREATER_EQUAL: // expr >= expr
|
case ET_GREATER: // expr > expr
|
case ET_GREATER: // expr > expr
|
case ET_BIT_OR: // expr | expr
|
case ET_BIT_OR: // expr | expr
|
case ET_BIT_AND: // expr & expr
|
case ET_BIT_AND: // expr & expr
|
case ET_BIT_XOR: // expr ^ expr
|
case ET_BIT_XOR: // expr ^ expr
|
case ET_MULT: // expr * expr
|
case ET_MULT: // expr * expr
|
case ET_DIV: // expr / expr
|
case ET_DIV: // expr / expr
|
case ET_MOD: // expr % expr
|
case ET_MOD: // expr % expr
|
return MaxType(left, right);
|
return MaxType(left, right);
|
|
|
case ET_LOG_OR: // expr || expr
|
case ET_LOG_OR: // expr || expr
|
case ET_LOG_AND: // expr && expr
|
case ET_LOG_AND: // expr && expr
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
|
|
case ET_FUNCALL: // expr ( ... )
|
case ET_FUNCALL: // expr ( ... )
|
return left->FunReturnType();
|
return left->FunReturnType();
|
|
|
case ET_ELEMENT: // expr [ expr ]
|
case ET_ELEMENT: // expr [ expr ]
|
return left->GetType()->ContentOf();
|
return left->GetType()->ContentOf();
|
}
|
}
|
assert(0 && "Bad binary operator");
|
assert(0 && "Bad binary operator");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * AdditionExpression::SetType()
|
TypeName * AdditionExpression::SetType()
|
{
|
{
|
assert(left);
|
assert(left);
|
assert(right);
|
assert(right);
|
|
|
if (left->GetType()->IsNumericType() && right->GetType()->IsNumericType())
|
if (left->GetType()->IsNumericType() && right->GetType()->IsNumericType())
|
return MaxType(left, right);
|
return MaxType(left, right);
|
|
|
if (left ->GetType()->IsNumericType()) return right->GetType();
|
if (left ->GetType()->IsNumericType()) return right->GetType();
|
if (right->GetType()->IsNumericType()) return left ->GetType();
|
if (right->GetType()->IsNumericType()) return left ->GetType();
|
|
|
fprintf(stderr, "Illegal pointer arithmetic\n");
|
fprintf(stderr, "Illegal pointer arithmetic\n");
|
semantic_errors++;
|
semantic_errors++;
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * SubtractionExpression::SetType()
|
TypeName * SubtractionExpression::SetType()
|
{
|
{
|
assert(left);
|
assert(left);
|
assert(right);
|
assert(right);
|
|
|
if (left->GetType()->IsNumericType() && right->GetType()->IsNumericType())
|
if (left->GetType()->IsNumericType() && right->GetType()->IsNumericType())
|
return MaxType(left, right);
|
return MaxType(left, right);
|
|
|
if (left ->GetType()->IsNumericType()) return right->GetType();
|
if (left ->GetType()->IsNumericType()) return right->GetType();
|
if (right->GetType()->IsNumericType()) return left ->GetType();
|
if (right->GetType()->IsNumericType()) return left ->GetType();
|
|
|
// TODO: check pointer compatibility
|
// TODO: check pointer compatibility
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * CondExpression::SetType()
|
TypeName * CondExpression::SetType()
|
{
|
{
|
// TODO: check argument compatibility
|
// TODO: check argument compatibility
|
return right->GetType();
|
return right->GetType();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * ArgListExpression::SetType()
|
TypeName * ArgListExpression::SetType()
|
{
|
{
|
assert(0);
|
assert(0);
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Expression::SetType(TypeName * t)
|
void Expression::SetType(TypeName * t)
|
{
|
{
|
assert(!type_name);
|
assert(!type_name);
|
type_name = t;
|
type_name = t;
|
assert(type_name);
|
assert(type_name);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * Expression::GetType()
|
TypeName * Expression::GetType()
|
{
|
{
|
if (!type_name) type_name = SetType();
|
if (!type_name) type_name = SetType();
|
|
|
assert(type_name);
|
assert(type_name);
|
return type_name;
|
return type_name;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool Expression::IsPointer()
|
bool Expression::IsPointer()
|
{
|
{
|
return GetType()->IsPointer();
|
return GetType()->IsPointer();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool Expression::IsArray()
|
bool Expression::IsArray()
|
{
|
{
|
return GetType()->IsArray();
|
return GetType()->IsArray();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool Expression::IsUnsigned()
|
bool Expression::IsUnsigned()
|
{
|
{
|
return GetType()->IsUnsigned();
|
return GetType()->IsUnsigned();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Expression::PointeeSize()
|
int Expression::PointeeSize()
|
{
|
{
|
return GetType()->GetPointeeSize();
|
return GetType()->GetPointeeSize();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Expression::GetSize()
|
int Expression::GetSize()
|
{
|
{
|
return GetType()->GetSize();
|
return GetType()->GetSize();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
SUW Expression::GetSUW()
|
SUW Expression::GetSUW()
|
{
|
{
|
return GetType()->GetSUW();
|
return GetType()->GetSUW();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void IdentifierExpression::Emit(FILE * out)
|
void IdentifierExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(varname);
|
assert(varname);
|
EmitStart(out);
|
EmitStart(out);
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "expr_type = \"identifier\" (%s)\n", varname);
|
fprintf(out, "expr_type = \"identifier\" (%s)\n", varname);
|
|
|
const int spos = Name::FindPos(varname);
|
const int spos = Name::FindPos(varname);
|
if (spos == 1)
|
if (spos == 1)
|
{
|
{
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
}
|
}
|
else
|
else
|
{
|
{
|
if (spos == 0) Backend::load_rr_var(varname, GetSUW());
|
if (spos == 0) Backend::load_rr_var(varname, GetSUW());
|
else Backend::load_rr_var(varname, spos, GetSUW());
|
else Backend::load_rr_var(varname, spos, GetSUW());
|
}
|
}
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void IdentifierExpression::Emit_to_ll(FILE * out)
|
void IdentifierExpression::Emit_to_ll(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
EmitIndent(out);
|
EmitIndent(out);
|
fprintf(out, "expr_type = \"identifier\" (%s)\n", varname);
|
fprintf(out, "expr_type = \"identifier\" (%s)\n", varname);
|
|
|
assert(varname);
|
assert(varname);
|
const int spos = Name::FindPos(varname);
|
const int spos = Name::FindPos(varname);
|
if (spos == 1)
|
if (spos == 1)
|
{
|
{
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
}
|
}
|
else
|
else
|
{
|
{
|
if (spos == 0) Backend::load_ll_var(varname, GetSUW());
|
if (spos == 0) Backend::load_ll_var(varname, GetSUW());
|
else Backend::load_ll_var(varname, spos, GetSUW());
|
else Backend::load_ll_var(varname, spos, GetSUW());
|
}
|
}
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StringExpression::Emit(FILE * out)
|
void StringExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(string_constant);
|
assert(string_constant);
|
string_constant->EmitValue_RR(out);
|
string_constant->EmitValue_RR(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StringExpression::EmitAddress(FILE * out)
|
void StringExpression::EmitAddress(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(string_constant);
|
assert(string_constant);
|
string_constant->EmitValue_RR(out);
|
string_constant->EmitValue_RR(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void StringExpression::Emit_to_ll(FILE * out)
|
void StringExpression::Emit_to_ll(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(string_constant);
|
assert(string_constant);
|
string_constant->EmitValue_LL(out);
|
string_constant->EmitValue_LL(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void NumericExpression::Emit(FILE * out)
|
void NumericExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(int_value);
|
assert(int_value);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(int_value);
|
assert(int_value);
|
int_value->EmitValue_RR(out);
|
int_value->EmitValue_RR(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void NumericExpression::Emit_to_ll(FILE * out)
|
void NumericExpression::Emit_to_ll(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(int_value);
|
assert(int_value);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(int_value);
|
assert(int_value);
|
int_value->EmitValue_LL(out);
|
int_value->EmitValue_LL(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void CondExpression::Emit(FILE * out)
|
void CondExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(left);
|
assert(left);
|
assert(middle);
|
assert(middle);
|
assert(right);
|
assert(right);
|
ExpressionStatement sm(middle);
|
ExpressionStatement sm(middle);
|
ExpressionStatement sr(right);
|
ExpressionStatement sr(right);
|
IfElseStatement sel(left, &sm, &sr);
|
IfElseStatement sel(left, &sm, &sr);
|
sel.Emit(out);
|
sel.Emit(out);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void BinaryExpression::EmitAddress(FILE * out)
|
void BinaryExpression::EmitAddress(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(left);
|
assert(left);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_ELEMENT: // expr[expr]
|
case ET_ELEMENT: // expr[expr]
|
{
|
{
|
if (left->IsPointer())
|
if (left->IsPointer())
|
{
|
{
|
assert(right);
|
assert(right);
|
right->Emit(out);
|
right->Emit(out);
|
Backend::scale_rr(left->GetType()->GetPointeeSize());
|
Backend::scale_rr(left->GetType()->GetPointeeSize());
|
Backend::push_rr(WO);
|
Backend::push_rr(WO);
|
left->Emit(out);
|
left->Emit(out);
|
Backend::pop_ll(WO);
|
Backend::pop_ll(WO);
|
Backend::compute_binary(ET_ADD, true, "+ (element)");
|
Backend::compute_binary(ET_ADD, true, "+ (element)");
|
}
|
}
|
else if (left->IsArray())
|
else if (left->IsArray())
|
{
|
{
|
assert(right);
|
assert(right);
|
right->Emit(out);
|
right->Emit(out);
|
Backend::scale_rr(left->GetType()->GetPointeeSize());
|
Backend::scale_rr(left->GetType()->GetPointeeSize());
|
left->AddAddress(out);
|
left->AddAddress(out);
|
}
|
}
|
else
|
else
|
{
|
{
|
left->GetType()->Print(out);
|
left->GetType()->Print(out);
|
fprintf(stderr, " is not a pointer\n");
|
fprintf(stderr, " is not a pointer\n");
|
semantic_errors++;
|
semantic_errors++;
|
}
|
}
|
}
|
}
|
break;
|
break;
|
|
|
default:
|
default:
|
fprintf(stderr, "'expr %s expr' is not an lvalue\n",
|
fprintf(stderr, "'expr %s expr' is not an lvalue\n",
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
semantic_errors++;
|
semantic_errors++;
|
break;
|
break;
|
}
|
}
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void UnaryExpression::EmitAddress(FILE * out)
|
void UnaryExpression::EmitAddress(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(right);
|
assert(right);
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_CAST: // (type) expr
|
case ET_CAST: // (type) expr
|
case ET_CONJUGATE: // + expr
|
case ET_CONJUGATE: // + expr
|
case ET_LOG_NOT: // ! expr
|
case ET_LOG_NOT: // ! expr
|
case ET_NEGATE: // - expr
|
case ET_NEGATE: // - expr
|
case ET_COMPLEMENT: // ~ expr
|
case ET_COMPLEMENT: // ~ expr
|
fprintf(stderr, "'%s expr' is not an lvalue\n",
|
fprintf(stderr, "'%s expr' is not an lvalue\n",
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
semantic_errors++;
|
semantic_errors++;
|
break;
|
break;
|
|
|
case ET_CONTENT: // * expr
|
case ET_CONTENT: // * expr
|
right->Emit(out);
|
right->Emit(out);
|
break;
|
break;
|
|
|
case ET_ADDRESS: // & expr
|
case ET_ADDRESS: // & expr
|
right->EmitAddress(out);
|
right->EmitAddress(out);
|
break;
|
break;
|
|
|
default: assert(0 && "Bad expr_type");
|
default: assert(0 && "Bad expr_type");
|
}
|
}
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void UnaryExpression::EmitInitialization(FILE * out, int size)
|
void UnaryExpression::EmitInitialization(FILE * out, int size)
|
{
|
{
|
assert(this);
|
assert(this);
|
assert(right);
|
assert(right);
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_CAST: // (type)expr
|
case ET_CAST: // (type)expr
|
right->EmitInitialization(out, size);
|
right->EmitInitialization(out, size);
|
return;
|
return;
|
|
|
case ET_ADDRESS: // & expr
|
case ET_ADDRESS: // & expr
|
if (size != 2) right->Emit(stderr);
|
if (size != 2) right->Emit(stderr);
|
assert(size == 2);
|
assert(size == 2);
|
if (right->IsVariable())
|
if (right->IsVariable())
|
{
|
{
|
const char * vname = right->GetVarname();
|
const char * vname = right->GetVarname();
|
assert(vname);
|
assert(vname);
|
|
|
// check that var is declared
|
// check that var is declared
|
const int spos = Name::FindPos(vname);
|
const int spos = Name::FindPos(vname);
|
if (spos == 1)
|
if (spos == 1)
|
{
|
{
|
fprintf(stderr, "Variable %s not declared\n", vname);
|
fprintf(stderr, "Variable %s not declared\n", vname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
fprintf(out, "\t.WORD\tC%s\t\t\t; & %s\n", vname, vname);
|
fprintf(out, "\t.WORD\tC%s\t\t\t; & %s\n", vname, vname);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
|
|
fprintf(stderr, "Non-const initializer (not supported)\n");
|
fprintf(stderr, "Non-const initializer (not supported)\n");
|
semantic_errors++;
|
semantic_errors++;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void UnaryExpression::Emit(FILE * out)
|
void UnaryExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(right);
|
assert(right);
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_PREINC:
|
case ET_PREINC:
|
case ET_PREDEC:
|
case ET_PREDEC:
|
{
|
{
|
BinExprType op = ET_ADD;
|
BinExprType op = ET_ADD;
|
const char * ops = "++";
|
const char * ops = "++";
|
if (expr_type == ET_PREDEC)
|
if (expr_type == ET_PREDEC)
|
{
|
{
|
op = ET_SUB;
|
op = ET_SUB;
|
ops = "--";
|
ops = "--";
|
}
|
}
|
|
|
int amount = 1;
|
int amount = 1;
|
if (right->IsPointer())
|
if (right->IsPointer())
|
amount = right->GetType()->GetPointeeSize();
|
amount = right->GetType()->GetPointeeSize();
|
|
|
if (right->IsVariable())
|
if (right->IsVariable())
|
{
|
{
|
right->Emit(out);
|
right->Emit(out);
|
Backend::compute_binary(op, true, ops, amount);
|
Backend::compute_binary(op, true, ops, amount);
|
right->EmitAssign(out);
|
right->EmitAssign(out);
|
break;
|
break;
|
}
|
}
|
|
|
right->EmitAddress(out);
|
right->EmitAddress(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
Backend::content(right->GetSUW());
|
Backend::content(right->GetSUW());
|
Backend::compute_binary(op, true, ops, amount);
|
Backend::compute_binary(op, true, ops, amount);
|
Backend::assign(right->GetSUW());
|
Backend::assign(right->GetSUW());
|
}
|
}
|
break;
|
break;
|
|
|
case ET_LOG_NOT: // ! expr
|
case ET_LOG_NOT: // ! expr
|
case ET_NEGATE: // - expr
|
case ET_NEGATE: // - expr
|
case ET_COMPLEMENT: // ~ expr
|
case ET_COMPLEMENT: // ~ expr
|
right->Emit(out);
|
right->Emit(out);
|
Backend::compute_unary(expr_type, GetPretty(expr_type));
|
Backend::compute_unary(expr_type, GetPretty(expr_type));
|
break;
|
break;
|
|
|
case ET_ADDRESS: // & expr
|
case ET_ADDRESS: // & expr
|
right->EmitAddress(out);
|
right->EmitAddress(out);
|
break;
|
break;
|
|
|
case ET_CONTENT: // * expr
|
case ET_CONTENT: // * expr
|
right->Emit(out);
|
right->Emit(out);
|
Backend::content(GetSUW());
|
Backend::content(GetSUW());
|
break;
|
break;
|
|
|
case ET_CONJUGATE: // + expr
|
case ET_CONJUGATE: // + expr
|
right->Emit(out);
|
right->Emit(out);
|
break;
|
break;
|
|
|
case ET_CAST: // (type) expr
|
case ET_CAST: // (type) expr
|
right->Emit(out);
|
right->Emit(out);
|
break;
|
break;
|
|
|
default: assert(0 && "Bad expr_type");
|
default: assert(0 && "Bad expr_type");
|
}
|
}
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void BinaryExpression::Emit(FILE * out)
|
void BinaryExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
((TypeName *)GetType())->Emit(out);
|
((TypeName *)GetType())->Emit(out);
|
|
|
assert(left);
|
assert(left);
|
assert(right || expr_type == ET_FUNCALL); // zero if no args
|
assert(right || expr_type == ET_FUNCALL); // zero if no args
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_FUNCALL:
|
case ET_FUNCALL:
|
left ->EmitCall(out, right);
|
left ->EmitCall(out, right);
|
break;
|
break;
|
|
|
case ET_LIST:
|
case ET_LIST:
|
left ->Emit(out);
|
left ->Emit(out);
|
right->Emit(out);
|
right->Emit(out);
|
break;
|
break;
|
|
|
case ET_ASSIGN: // expr = expr
|
case ET_ASSIGN: // expr = expr
|
right->Emit(out);
|
right->Emit(out);
|
if (left->IsVariable())
|
if (left->IsVariable())
|
{
|
{
|
left->EmitAssign(out);
|
left->EmitAssign(out);
|
break;
|
break;
|
}
|
}
|
Backend::push_rr(left->GetSUW());
|
Backend::push_rr(left->GetSUW());
|
left->EmitAddress(out);
|
left->EmitAddress(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
Backend::pop_rr(left->GetSUW());
|
Backend::pop_rr(left->GetSUW());
|
Backend::assign(GetSize());
|
Backend::assign(GetSize());
|
break;
|
break;
|
|
|
case ET_BIT_OR: // expr | expr
|
case ET_BIT_OR: // expr | expr
|
case ET_BIT_AND: // expr & expr
|
case ET_BIT_AND: // expr & expr
|
case ET_BIT_XOR: // expr ^ expr
|
case ET_BIT_XOR: // expr ^ expr
|
case ET_MULT: // expr * expr
|
case ET_MULT: // expr * expr
|
case ET_DIV: // expr / expr
|
case ET_DIV: // expr / expr
|
case ET_MOD: // expr % expr
|
case ET_MOD: // expr % expr
|
case ET_LEFT: // expr << expr
|
case ET_LEFT: // expr << expr
|
case ET_RIGHT: // expr >> expr
|
case ET_RIGHT: // expr >> expr
|
case ET_EQUAL: // expr == expr
|
case ET_EQUAL: // expr == expr
|
case ET_NOT_EQUAL: // expr != expr
|
case ET_NOT_EQUAL: // expr != expr
|
case ET_LESS_EQUAL: // expr <= expr
|
case ET_LESS_EQUAL: // expr <= expr
|
case ET_LESS: // expr < expr
|
case ET_LESS: // expr < expr
|
case ET_GREATER_EQUAL: // expr >= expr
|
case ET_GREATER_EQUAL: // expr >= expr
|
case ET_GREATER: // expr > expr
|
case ET_GREATER: // expr > expr
|
if (right->IsConstant())
|
if (right->IsConstant())
|
{
|
{
|
left->Emit(out);
|
left->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
GetPretty(expr_type),
|
GetPretty(expr_type),
|
right->GetConstantNumericValue());
|
right->GetConstantNumericValue());
|
}
|
}
|
else if (left->IsConstant())
|
else if (left->IsConstant())
|
{
|
{
|
right->Emit(out);
|
right->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
left->GetConstantNumericValue(),
|
left->GetConstantNumericValue(),
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
}
|
}
|
else if (right->IsVariable())
|
else if (right->IsVariable())
|
{
|
{
|
left->Emit(out);
|
left->Emit(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
right->Emit(out);
|
right->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
}
|
}
|
else if (left->IsVariable())
|
else if (left->IsVariable())
|
{
|
{
|
right->Emit(out);
|
right->Emit(out);
|
left->Emit_to_ll(out);
|
left->Emit_to_ll(out);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
}
|
}
|
else
|
else
|
{
|
{
|
left->Emit(out);
|
left->Emit(out);
|
Backend::push_rr(WO);
|
Backend::push_rr(WO);
|
right->Emit(out);
|
right->Emit(out);
|
Backend::pop_ll(WO);
|
Backend::pop_ll(WO);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
}
|
}
|
break;
|
break;
|
|
|
case ET_LOG_AND: // expr && expr
|
case ET_LOG_AND: // expr && expr
|
// if (left) right;
|
// if (left) right;
|
{
|
{
|
ExpressionStatement r(right);
|
ExpressionStatement r(right);
|
IfElseStatement i(left, &r, 0);
|
IfElseStatement i(left, &r, 0);
|
i.Emit(out);
|
i.Emit(out);
|
}
|
}
|
break;
|
break;
|
|
|
case ET_LOG_OR: // expr || expr
|
case ET_LOG_OR: // expr || expr
|
// if (left) ; else right;
|
// if (left) ; else right;
|
{
|
{
|
ExpressionStatement r(right);
|
ExpressionStatement r(right);
|
IfElseStatement i(left, 0, &r);
|
IfElseStatement i(left, 0, &r);
|
i.Emit(out);
|
i.Emit(out);
|
}
|
}
|
break;
|
break;
|
|
|
case ET_ELEMENT: // expr [ expr ]
|
case ET_ELEMENT: // expr [ expr ]
|
EmitAddress(out);
|
EmitAddress(out);
|
Backend::content(left->GetType()->ContentOf()->GetSUW());
|
Backend::content(left->GetType()->ContentOf()->GetSUW());
|
break;
|
break;
|
|
|
default: assert(0 && "Bad expr_type");
|
default: assert(0 && "Bad expr_type");
|
}
|
}
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void AdditionExpression::Emit(FILE * out)
|
void AdditionExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(left);
|
assert(left);
|
assert(right);
|
assert(right);
|
|
|
Expression * lft = left;
|
Expression * lft = left;
|
Expression * rht = right;
|
Expression * rht = right;
|
|
|
// move pointer to left side
|
// move pointer to left side
|
if (right->IsPointer() || right->IsArray())
|
if (right->IsPointer() || right->IsArray())
|
{
|
{
|
lft = right;
|
lft = right;
|
rht = left;
|
rht = left;
|
}
|
}
|
|
|
if (rht->IsPointer() || rht->IsArray()) // error: pinter + pointer
|
if (rht->IsPointer() || rht->IsArray()) // error: pinter + pointer
|
{
|
{
|
fprintf(stderr, "Bad pointer arithmetic\n");
|
fprintf(stderr, "Bad pointer arithmetic\n");
|
semantic_errors++;
|
semantic_errors++;
|
EmitEnd(out);
|
EmitEnd(out);
|
return;
|
return;
|
}
|
}
|
|
|
int rscale = 1;
|
int rscale = 1;
|
if (lft ->IsPointer()) rscale = lft ->PointeeSize();
|
if (lft ->IsPointer()) rscale = lft ->PointeeSize();
|
|
|
if (rht->IsConstant())
|
if (rht->IsConstant())
|
{
|
{
|
lft->Emit(out);
|
lft->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(), GetPretty(ET_ADD),
|
Backend::compute_binary(expr_type, IsUnsigned(), GetPretty(ET_ADD),
|
rscale * rht->GetConstantNumericValue());
|
rscale * rht->GetConstantNumericValue());
|
EmitEnd(out);
|
EmitEnd(out);
|
return;
|
return;
|
}
|
}
|
|
|
if (lft->IsConstant())
|
if (lft->IsConstant())
|
{
|
{
|
rht->Emit(out);
|
rht->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
lft->GetConstantNumericValue(),
|
lft->GetConstantNumericValue(),
|
GetPretty(ET_ADD));
|
GetPretty(ET_ADD));
|
EmitEnd(out);
|
EmitEnd(out);
|
return;
|
return;
|
}
|
}
|
|
|
if (rht->IsVariable())
|
if (rht->IsVariable())
|
{
|
{
|
lft->Emit(out);
|
lft->Emit(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
rht->Emit(out);
|
rht->Emit(out);
|
}
|
}
|
else if (lft->IsVariable())
|
else if (lft->IsVariable())
|
{
|
{
|
rht->Emit(out);
|
rht->Emit(out);
|
lft->Emit_to_ll(out);
|
lft->Emit_to_ll(out);
|
}
|
}
|
else
|
else
|
{
|
{
|
rht->Emit(out);
|
rht->Emit(out);
|
Backend::push_rr(WO);
|
Backend::push_rr(WO);
|
lft->Emit(out);
|
lft->Emit(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
Backend::pop_rr(WO);
|
Backend::pop_rr(WO);
|
}
|
}
|
|
|
Backend::scale_rr(rscale);
|
Backend::scale_rr(rscale);
|
Backend::compute_binary(ET_ADD, IsUnsigned(), GetPretty(ET_ADD));
|
Backend::compute_binary(ET_ADD, IsUnsigned(), GetPretty(ET_ADD));
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void SubtractionExpression::Emit(FILE * out)
|
void SubtractionExpression::Emit(FILE * out)
|
{
|
{
|
assert(this);
|
assert(this);
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(left);
|
assert(left);
|
assert(right);
|
assert(right);
|
|
|
int rscale = 1;
|
int rscale = 1;
|
int uscale = 1;
|
int uscale = 1;
|
if (left->IsPointer())
|
if (left->IsPointer())
|
{
|
{
|
if (right->IsPointer()) uscale = left->PointeeSize();
|
if (right->IsPointer()) uscale = left->PointeeSize();
|
else rscale = left->PointeeSize();
|
else rscale = left->PointeeSize();
|
}
|
}
|
else if (right->IsPointer())
|
else if (right->IsPointer())
|
{
|
{
|
fprintf(stderr, "Bad pointer arithmetic\n");
|
fprintf(stderr, "Bad pointer arithmetic\n");
|
semantic_errors++;
|
semantic_errors++;
|
EmitEnd(out);
|
EmitEnd(out);
|
return;
|
return;
|
}
|
}
|
|
|
if (left->IsConstant())
|
if (left->IsConstant())
|
{
|
{
|
right->Emit(out);
|
right->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
Backend::compute_binary(expr_type, IsUnsigned(),
|
left->GetConstantNumericValue(),
|
left->GetConstantNumericValue(),
|
GetPretty(ET_SUB));
|
GetPretty(ET_SUB));
|
EmitEnd(out);
|
EmitEnd(out);
|
return;
|
return;
|
}
|
}
|
|
|
if (right->IsConstant())
|
if (right->IsConstant())
|
{
|
{
|
left->Emit(out);
|
left->Emit(out);
|
Backend::compute_binary(expr_type, IsUnsigned(), GetPretty(ET_SUB),
|
Backend::compute_binary(expr_type, IsUnsigned(), GetPretty(ET_SUB),
|
rscale * right->GetConstantNumericValue());
|
rscale * right->GetConstantNumericValue());
|
EmitEnd(out);
|
EmitEnd(out);
|
return;
|
return;
|
}
|
}
|
|
|
if (right->IsVariable())
|
if (right->IsVariable())
|
{
|
{
|
left->Emit(out);
|
left->Emit(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
right->Emit(out);
|
right->Emit(out);
|
}
|
}
|
else if (left->IsVariable())
|
else if (left->IsVariable())
|
{
|
{
|
right->Emit(out);
|
right->Emit(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
left->Emit_to_ll(out);
|
left->Emit_to_ll(out);
|
}
|
}
|
else
|
else
|
{
|
{
|
right->Emit(out);
|
right->Emit(out);
|
Backend::push_rr(WO);
|
Backend::push_rr(WO);
|
left->Emit(out);
|
left->Emit(out);
|
Backend::move_rr_to_ll();
|
Backend::move_rr_to_ll();
|
Backend::pop_rr(WO);
|
Backend::pop_rr(WO);
|
}
|
}
|
|
|
Backend::scale_rr(rscale);
|
Backend::scale_rr(rscale);
|
Backend::compute_binary(ET_SUB, IsUnsigned(), GetPretty(ET_SUB));
|
Backend::compute_binary(ET_SUB, IsUnsigned(), GetPretty(ET_SUB));
|
Backend::unscale_rr(uscale, right->IsUnsigned());
|
Backend::unscale_rr(uscale, right->IsUnsigned());
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * Expression::GetPrettyName(const char * pretty)
|
const char * Expression::GetPrettyName(const char * pretty)
|
{
|
{
|
assert(pretty);
|
assert(pretty);
|
const int plen = strlen(pretty);
|
const int plen = strlen(pretty);
|
char * ret = new char[plen + 10];
|
char * ret = new char[plen + 10];
|
sprintf(ret, "Expr %s", pretty);
|
sprintf(ret, "Expr %s", pretty);
|
return ret;
|
return ret;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * UnaryExpression::GetPretty(UnaExprType expr_type)
|
const char * UnaryExpression::GetPretty(UnaExprType expr_type)
|
{
|
{
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_ADDRESS: return "& r";
|
case ET_ADDRESS: return "& r";
|
case ET_CAST: return "()r";
|
case ET_CAST: return "()r";
|
case ET_CONTENT: return "* r";
|
case ET_CONTENT: return "* r";
|
case ET_CONJUGATE: return "+ r";
|
case ET_CONJUGATE: return "+ r";
|
case ET_NEGATE: return "- r";
|
case ET_NEGATE: return "- r";
|
case ET_COMPLEMENT: return "~ r";
|
case ET_COMPLEMENT: return "~ r";
|
case ET_LOG_NOT: return "! r";
|
case ET_LOG_NOT: return "! r";
|
case ET_POSTINC: return "r++";
|
case ET_POSTINC: return "r++";
|
case ET_POSTDEC: return "r--";
|
case ET_POSTDEC: return "r--";
|
case ET_PREINC: return "++r";
|
case ET_PREINC: return "++r";
|
case ET_PREDEC: return "--r";
|
case ET_PREDEC: return "--r";
|
|
|
default: return "BAD UNARY EXPR_TYPE";
|
default: return "BAD UNARY EXPR_TYPE";
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
const char * BinaryExpression::GetPretty(BinExprType expr_type)
|
const char * BinaryExpression::GetPretty(BinExprType expr_type)
|
{
|
{
|
switch(expr_type)
|
switch(expr_type)
|
{
|
{
|
case ET_LIST: return "l , r";
|
case ET_LIST: return "l , r";
|
case ET_ARGLIST: return "(l , r)";
|
case ET_ARGLIST: return "(l , r)";
|
case ET_ASSIGN: return "l = r";
|
case ET_ASSIGN: return "l = r";
|
case ET_MULT_ASSIGN: return "l *- r";
|
case ET_MULT_ASSIGN: return "l *- r";
|
case ET_DIV_ASSIGN: return "l /= r";
|
case ET_DIV_ASSIGN: return "l /= r";
|
case ET_MOD_ASSIGN: return "l %= r";
|
case ET_MOD_ASSIGN: return "l %= r";
|
case ET_ADD_ASSIGN: return "l += r";
|
case ET_ADD_ASSIGN: return "l += r";
|
case ET_SUB_ASSIGN: return "l -= r";
|
case ET_SUB_ASSIGN: return "l -= r";
|
case ET_LEFT_ASSIGN: return "l <<= r";
|
case ET_LEFT_ASSIGN: return "l <<= r";
|
case ET_RIGHT_ASSIGN: return "l >>= r";
|
case ET_RIGHT_ASSIGN: return "l >>= r";
|
case ET_AND_ASSIGN: return "l & r";
|
case ET_AND_ASSIGN: return "l & r";
|
case ET_XOR_ASSIGN: return "l ^ r";
|
case ET_XOR_ASSIGN: return "l ^ r";
|
case ET_OR_ASSIGN: return "l | r";
|
case ET_OR_ASSIGN: return "l | r";
|
case ET_LOG_OR: return "l || r";
|
case ET_LOG_OR: return "l || r";
|
case ET_LOG_AND: return "l && r";
|
case ET_LOG_AND: return "l && r";
|
case ET_BIT_OR: return "l | r";
|
case ET_BIT_OR: return "l | r";
|
case ET_BIT_AND: return "l & r";
|
case ET_BIT_AND: return "l & r";
|
case ET_BIT_XOR: return "l ^ r";
|
case ET_BIT_XOR: return "l ^ r";
|
case ET_EQUAL: return "l == r";
|
case ET_EQUAL: return "l == r";
|
case ET_NOT_EQUAL: return "l != r";
|
case ET_NOT_EQUAL: return "l != r";
|
case ET_LESS_EQUAL: return "l <= r";
|
case ET_LESS_EQUAL: return "l <= r";
|
case ET_LESS: return "l < r";
|
case ET_LESS: return "l < r";
|
case ET_GREATER_EQUAL: return "l >= r";
|
case ET_GREATER_EQUAL: return "l >= r";
|
case ET_GREATER: return "l > r";
|
case ET_GREATER: return "l > r";
|
case ET_LEFT: return "l << r";
|
case ET_LEFT: return "l << r";
|
case ET_RIGHT: return "l >> r";
|
case ET_RIGHT: return "l >> r";
|
case ET_ADD: return "l + r";
|
case ET_ADD: return "l + r";
|
case ET_SUB: return "l - r";
|
case ET_SUB: return "l - r";
|
case ET_MULT: return "l * r";
|
case ET_MULT: return "l * r";
|
case ET_DIV: return "l / r";
|
case ET_DIV: return "l / r";
|
case ET_MOD: return "l % r";
|
case ET_MOD: return "l % r";
|
case ET_FUNCALL: return "l(r)";
|
case ET_FUNCALL: return "l(r)";
|
case ET_ELEMENT: return "l[r]";
|
case ET_ELEMENT: return "l[r]";
|
|
|
default: return "BAD BINARY EXPR_TYPE";
|
default: return "BAD BINARY EXPR_TYPE";
|
}
|
}
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void IdentifierExpression::EmitAssign(FILE * out)
|
void IdentifierExpression::EmitAssign(FILE * out)
|
{
|
{
|
assert(varname);
|
assert(varname);
|
const int spos = Name::FindPos(varname);
|
const int spos = Name::FindPos(varname);
|
if (spos == 1)
|
if (spos == 1)
|
{
|
{
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
if (spos == 0) Backend::store_rr_var(varname, GetSUW());
|
if (spos == 0) Backend::store_rr_var(varname, GetSUW());
|
else Backend::store_rr_var(varname, spos, GetSUW());
|
else Backend::store_rr_var(varname, spos, GetSUW());
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void IdentifierExpression::AddAddress(FILE * out)
|
void IdentifierExpression::AddAddress(FILE * out)
|
{
|
{
|
assert(varname);
|
assert(varname);
|
const int spos = Name::FindPos(varname);
|
const int spos = Name::FindPos(varname);
|
if (spos == 1)
|
if (spos == 1)
|
{
|
{
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
if (spos == 0) Backend::add_address(varname);
|
if (spos == 0) Backend::add_address(varname);
|
else Expression::AddAddress(out);
|
else Expression::AddAddress(out);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void IdentifierExpression::EmitAddress(FILE * out)
|
void IdentifierExpression::EmitAddress(FILE * out)
|
{
|
{
|
assert(varname);
|
assert(varname);
|
const int spos = Name::FindPos(varname);
|
const int spos = Name::FindPos(varname);
|
if (spos == 1)
|
if (spos == 1)
|
{
|
{
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
fprintf(stderr, "Variable %s not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
|
|
if (spos == 0) Backend::load_address(varname);
|
if (spos == 0) Backend::load_address(varname);
|
else Backend::load_address(varname, spos);
|
else Backend::load_address(varname, spos);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void IdentifierExpression::EmitInitialization(FILE * out, int size)
|
void IdentifierExpression::EmitInitialization(FILE * out, int size)
|
{
|
{
|
assert(varname);
|
assert(varname);
|
fprintf(out, "\t.WORD\tC%s\n", varname);
|
fprintf(out, "\t.WORD\tC%s\n", varname);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Expression::EmitInitialization(FILE * out, int size)
|
void Expression::EmitInitialization(FILE * out, int size)
|
{
|
{
|
fprintf(stderr, "TODO: EmitInitialization %s\n", GetNodeType());
|
fprintf(stderr, "TODO: EmitInitialization %s\n", GetNodeType());
|
Emit(stderr);
|
Emit(stderr);
|
fprintf(stderr, "----: EmitInitialization %s\n", GetNodeType());
|
fprintf(stderr, "----: EmitInitialization %s\n", GetNodeType());
|
assert(0);
|
assert(0);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Expression::EmitAddress(FILE * out)
|
void Expression::EmitAddress(FILE * out)
|
{
|
{
|
fprintf(stderr, "TODO: Expression::EmitAddress() %s\n", GetNodeType());
|
fprintf(stderr, "TODO: Expression::EmitAddress() %s\n", GetNodeType());
|
Emit(stderr);
|
Emit(stderr);
|
fprintf(stderr, "----: Expression::EmitAddress() %s\n", GetNodeType());
|
fprintf(stderr, "----: Expression::EmitAddress() %s\n", GetNodeType());
|
assert(0);
|
assert(0);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Expression::AddAddress(FILE * out)
|
void Expression::AddAddress(FILE * out)
|
{
|
{
|
Backend::push_rr(WO);
|
Backend::push_rr(WO);
|
Emit(out);
|
Emit(out);
|
Backend::pop_ll(WO);
|
Backend::pop_ll(WO);
|
Backend::compute_binary(ET_ADD, true, "&l[r]");
|
Backend::compute_binary(ET_ADD, true, "&l[r]");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
BinExprType BinaryExpression::MapAssign(BinExprType et)
|
BinExprType BinaryExpression::MapAssign(BinExprType et)
|
{
|
{
|
switch(et)
|
switch(et)
|
{
|
{
|
case ET_MULT_ASSIGN: return ET_MULT;
|
case ET_MULT_ASSIGN: return ET_MULT;
|
case ET_DIV_ASSIGN: return ET_DIV;
|
case ET_DIV_ASSIGN: return ET_DIV;
|
case ET_MOD_ASSIGN: return ET_MOD;
|
case ET_MOD_ASSIGN: return ET_MOD;
|
case ET_LEFT_ASSIGN: return ET_LEFT;
|
case ET_LEFT_ASSIGN: return ET_LEFT;
|
case ET_RIGHT_ASSIGN: return ET_RIGHT;
|
case ET_RIGHT_ASSIGN: return ET_RIGHT;
|
case ET_AND_ASSIGN: return ET_BIT_AND;
|
case ET_AND_ASSIGN: return ET_BIT_AND;
|
case ET_XOR_ASSIGN: return ET_BIT_XOR;
|
case ET_XOR_ASSIGN: return ET_BIT_XOR;
|
case ET_OR_ASSIGN: return ET_BIT_OR;
|
case ET_OR_ASSIGN: return ET_BIT_OR;
|
}
|
}
|
|
|
assert(0 && "Bad expr_type");
|
assert(0 && "Bad expr_type");
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Expression::FunReturnSize()
|
int Expression::FunReturnSize()
|
{
|
{
|
TypeName * funtn = FunReturnType();
|
TypeName * funtn = FunReturnType();
|
assert(funtn);
|
assert(funtn);
|
|
|
return funtn->GetFunReturnSize();
|
return funtn->GetFunReturnSize();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * Expression::FunReturnType()
|
TypeName * Expression::FunReturnType()
|
{
|
{
|
TypeName * tn = GetType();
|
TypeName * tn = GetType();
|
assert(tn);
|
assert(tn);
|
return tn->GetFunReturnType();
|
return tn->GetFunReturnType();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Expression * IdentifierExpression::New(const char * s)
|
Expression * IdentifierExpression::New(const char * s)
|
{
|
{
|
int value;
|
int value;
|
bool is_enum = Name::FindEnum(s, value);
|
bool is_enum = Name::FindEnum(s, value);
|
|
|
if (!is_enum) return new IdentifierExpression(s);
|
if (!is_enum) return new IdentifierExpression(s);
|
|
|
int spos = Name::FindPos(s);
|
int spos = Name::FindPos(s);
|
|
|
if (spos != 1)
|
if (spos != 1)
|
{
|
{
|
fprintf(stderr, "Warning: variable %s shadows enum value\n", s);
|
fprintf(stderr, "Warning: variable %s shadows enum value\n", s);
|
return new IdentifierExpression(s);
|
return new IdentifierExpression(s);
|
}
|
}
|
|
|
return new NumericExpression(value);
|
return new NumericExpression(value);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * IdentifierExpression::FunReturnType()
|
TypeName * IdentifierExpression::FunReturnType()
|
{
|
{
|
assert(varname);
|
assert(varname);
|
|
|
TypeName * funtn = Name::FindType(varname);
|
TypeName * funtn = Name::FindType(varname);
|
if (funtn) return funtn->GetFunReturnType();
|
if (funtn) return funtn->GetFunReturnType();
|
|
|
fprintf(stderr, "Function '%s' not declared\n", varname);
|
fprintf(stderr, "Function '%s' not declared\n", varname);
|
semantic_errors++;
|
semantic_errors++;
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * BinaryExpression::MaxType(Expression * left, Expression * right)
|
TypeName * BinaryExpression::MaxType(Expression * left, Expression * right)
|
{
|
{
|
TypeName * ltype = left ->GetType(); assert(ltype);
|
TypeName * ltype = left ->GetType(); assert(ltype);
|
TypeName * rtype = right->GetType(); assert(rtype);
|
TypeName * rtype = right->GetType(); assert(rtype);
|
|
|
if (!ltype->IsNumericType())
|
if (!ltype->IsNumericType())
|
{
|
{
|
if ( expr_type == ET_EQUAL || expr_type == ET_NOT_EQUAL
|
if ( expr_type == ET_EQUAL || expr_type == ET_NOT_EQUAL
|
|| expr_type == ET_LESS_EQUAL || expr_type == ET_LESS
|
|| expr_type == ET_LESS_EQUAL || expr_type == ET_LESS
|
|| expr_type == ET_GREATER_EQUAL || expr_type == ET_GREATER)
|
|| expr_type == ET_GREATER_EQUAL || expr_type == ET_GREATER)
|
{
|
{
|
if (ltype->IsPointer()) return ltype;
|
if (ltype->IsPointer()) return ltype;
|
}
|
}
|
|
|
fprintf(stderr, "Left argument of %s is not numeric\n",
|
fprintf(stderr, "Left argument of %s is not numeric\n",
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
semantic_errors++;
|
semantic_errors++;
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
|
|
if (!rtype->IsNumericType())
|
if (!rtype->IsNumericType())
|
{
|
{
|
if ( expr_type == ET_EQUAL || expr_type == ET_NOT_EQUAL
|
if ( expr_type == ET_EQUAL || expr_type == ET_NOT_EQUAL
|
|| expr_type == ET_LESS_EQUAL || expr_type == ET_LESS
|
|| expr_type == ET_LESS_EQUAL || expr_type == ET_LESS
|
|| expr_type == ET_GREATER_EQUAL || expr_type == ET_GREATER)
|
|| expr_type == ET_GREATER_EQUAL || expr_type == ET_GREATER)
|
{
|
{
|
if (rtype->IsPointer()) return rtype;
|
if (rtype->IsPointer()) return rtype;
|
}
|
}
|
|
|
fprintf(stderr, "Right argument of %s is not numeric\n",
|
fprintf(stderr, "Right argument of %s is not numeric\n",
|
GetPretty(expr_type));
|
GetPretty(expr_type));
|
semantic_errors++;
|
semantic_errors++;
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
|
|
Specifier spec = TS_INT;
|
Specifier spec = TS_INT;
|
|
|
if (ltype->IsUnsigned()) spec = (Specifier)(TS_INT | TS_UNSIGNED);
|
if (ltype->IsUnsigned()) spec = (Specifier)(TS_INT | TS_UNSIGNED);
|
if (rtype->IsUnsigned()) spec = (Specifier)(TS_INT | TS_UNSIGNED);
|
if (rtype->IsUnsigned()) spec = (Specifier)(TS_INT | TS_UNSIGNED);
|
return new TypeName(spec);
|
return new TypeName(spec);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int NumericExpression::GetConstantNumericValue() const
|
int NumericExpression::GetConstantNumericValue() const
|
{
|
{
|
assert(int_value);
|
assert(int_value);
|
return int_value->GetValue();
|
return int_value->GetValue();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Expression::GetConstantNumericValue() const
|
int Expression::GetConstantNumericValue() const
|
{
|
{
|
fprintf(stderr, "Non-constant value where numeric constant expected\n");
|
fprintf(stderr, "Non-constant value where numeric constant expected\n");
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
StringConstant * Expression::GetStringConstant() const
|
StringConstant * Expression::GetStringConstant() const
|
{
|
{
|
fprintf(stderr, "Non-constant value where string constant expected\n");
|
fprintf(stderr, "Non-constant value where string constant expected\n");
|
semantic_errors++;
|
semantic_errors++;
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void Expression::EmitCall(FILE * out, Expression * args)
|
void Expression::EmitCall(FILE * out, Expression * args)
|
{
|
{
|
TypeName * tname;
|
TypeName * tname;
|
|
|
tname = GetType();
|
tname = GetType();
|
assert(tname);
|
assert(tname);
|
|
|
ParameterDeclarationList * plist = tname->GetParameters();
|
ParameterDeclarationList * plist = tname->GetParameters();
|
|
|
int param_bytes_pushed = 0;
|
int param_bytes_pushed = 0;
|
if (args)
|
if (args)
|
{
|
{
|
if (!plist)
|
if (!plist)
|
{
|
{
|
const char * funname = GetVarname();
|
const char * funname = GetVarname();
|
if (funname == 0) funname = "";
|
if (funname == 0) funname = "";
|
fprintf(stderr,
|
fprintf(stderr,
|
"Arguments for function %s without parameters\n",
|
"Arguments for function %s without parameters\n",
|
funname);
|
funname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
param_bytes_pushed += args->EmitPush(out, plist);
|
param_bytes_pushed += args->EmitPush(out, plist);
|
}
|
}
|
else
|
else
|
{
|
{
|
if (plist)
|
if (plist)
|
{
|
{
|
const char * funname = GetVarname();
|
const char * funname = GetVarname();
|
if (funname == 0) funname = "";
|
if (funname == 0) funname = "";
|
fprintf(stderr,
|
fprintf(stderr,
|
"No arguments for function %s with parameters\n",
|
"No arguments for function %s with parameters\n",
|
funname);
|
funname);
|
semantic_errors++;
|
semantic_errors++;
|
return;
|
return;
|
}
|
}
|
}
|
}
|
|
|
// compute return value size
|
// compute return value size
|
const int ret_size = tname->GetFunReturnSize();
|
const int ret_size = tname->GetFunReturnSize();
|
param_bytes_pushed += Backend::push_return(ret_size);
|
param_bytes_pushed += Backend::push_return(ret_size);
|
|
|
if (GetType()->IsFunPtr())
|
if (GetType()->IsFunPtr())
|
{
|
{
|
Emit(out);
|
Emit(out);
|
Backend::call_ptr();
|
Backend::call_ptr();
|
}
|
}
|
else
|
else
|
{
|
{
|
assert(GetVarname());
|
assert(GetVarname());
|
Backend::call(GetVarname());
|
Backend::call(GetVarname());
|
}
|
}
|
|
|
Backend::pop(param_bytes_pushed);
|
Backend::pop(param_bytes_pushed);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int ArgListExpression::EmitPush(FILE * out, ParameterDeclarationList * args)
|
int ArgListExpression::EmitPush(FILE * out, ParameterDeclarationList * args)
|
{
|
{
|
EmitStart(out);
|
EmitStart(out);
|
|
|
assert(left);
|
assert(left);
|
assert(right);
|
assert(right);
|
|
|
ParameterDeclarationList * a = args;
|
ParameterDeclarationList * a = args;
|
for (int l = left->GetParaLength(); a && l; l--)
|
for (int l = left->GetParaLength(); a && l; l--)
|
{
|
{
|
if (!a->Head()->IsEllipsis()) a = a->Tail();
|
if (!a->Head()->IsEllipsis()) a = a->Tail();
|
}
|
}
|
|
|
if (a)
|
if (a)
|
{
|
{
|
const int rpush = right->EmitPush(out, a);
|
const int rpush = right->EmitPush(out, a);
|
const int lpush = left ->EmitPush(out, args);
|
const int lpush = left ->EmitPush(out, args);
|
|
|
EmitEnd(out);
|
EmitEnd(out);
|
return rpush + lpush;
|
return rpush + lpush;
|
}
|
}
|
|
|
semantic_errors++;
|
semantic_errors++;
|
EmitEnd(out);
|
EmitEnd(out);
|
return 0;
|
return 0;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int Expression::EmitPush(FILE * out, ParameterDeclarationList * args)
|
int Expression::EmitPush(FILE * out, ParameterDeclarationList * args)
|
{
|
{
|
assert(args);
|
assert(args);
|
|
|
ParameterDeclaration * pd = args->Head();
|
ParameterDeclaration * pd = args->Head();
|
assert(pd);
|
assert(pd);
|
|
|
TypeName * tname = pd->GetTypeName();
|
TypeName * tname = pd->GetTypeName();
|
assert(tname);
|
assert(tname);
|
|
|
SUW suw;
|
SUW suw;
|
|
|
pd->Emit(out); // just shows type
|
pd->Emit(out); // just shows type
|
if (tname->IsPointer() && GetType()->IsArray())
|
if (tname->IsPointer() && GetType()->IsArray())
|
{
|
{
|
EmitAddress(out);
|
EmitAddress(out);
|
suw = WO;
|
suw = WO;
|
}
|
}
|
else
|
else
|
{
|
{
|
Emit(out);
|
Emit(out);
|
suw = tname->GetSUW();
|
suw = tname->GetSUW();
|
}
|
}
|
|
|
Backend::push_rr(suw);
|
Backend::push_rr(suw);
|
|
|
if (suw == WO) return 2;
|
if (suw == WO) return 2;
|
return 1;
|
return 1;
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
int ArgListExpression::GetParaLength() const
|
int ArgListExpression::GetParaLength() const
|
{
|
{
|
assert(left);
|
assert(left);
|
assert(right);
|
assert(right);
|
|
|
return left->GetParaLength() + right->GetParaLength();
|
return left->GetParaLength() + right->GetParaLength();
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
AsmExpression::AsmExpression(StringConstant * string)
|
AsmExpression::AsmExpression(StringConstant * string)
|
: Expression("asm Expression")
|
: Expression("asm Expression")
|
{
|
{
|
asm_string = string->Kill();
|
asm_string = string->Kill();
|
assert(asm_string);
|
assert(asm_string);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void AsmExpression::Emit(FILE * out)
|
void AsmExpression::Emit(FILE * out)
|
{
|
{
|
Backend::asmbl(asm_string);
|
Backend::asmbl(asm_string);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
TypeName * AsmExpression::SetType()
|
TypeName * AsmExpression::SetType()
|
{
|
{
|
return new TypeName(TS_INT);
|
return new TypeName(TS_INT);
|
}
|
}
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|