ast_expr.cc 8.15 KB
/* File: ast_expr.cc
* -----------------
* Implementation of expression node classes.
*/
#include <string.h>
#include "ast_expr.h"
#include "ast_type.h"
#include "ast_decl.h"
#include "symtable.h"
IntConstant::IntConstant(yyltype loc, int val) : Expr(loc) {
value = val;
}
void IntConstant::PrintChildren(int indentLevel) {
printf("%d", value);
}
FloatConstant::FloatConstant(yyltype loc, double val) : Expr(loc) {
value = val;
}
void FloatConstant::PrintChildren(int indentLevel) {
printf("%g", value);
}
BoolConstant::BoolConstant(yyltype loc, bool val) : Expr(loc) {
value = val;
}
void BoolConstant::PrintChildren(int indentLevel) {
printf("%s", value ? "true" : "false");
}
VarExpr::VarExpr(yyltype loc, Identifier *ident) : Expr(loc) {
Assert(ident != NULL);
this->id = ident;
}
void VarExpr::PrintChildren(int indentLevel) {
id->Print(indentLevel+1);
}
Operator::Operator(yyltype loc, const char *tok) : Node(loc) {
Assert(tok != NULL);
strncpy(tokenString, tok, sizeof(tokenString));
}
void Operator::PrintChildren(int indentLevel) {
printf("%s",tokenString);
}
bool Operator::IsOp(const char *op) const {
return strcmp(tokenString, op) == 0;
}
CompoundExpr::CompoundExpr(Expr *l, Operator *o, Expr *r)
: Expr(Join(l->GetLocation(), r->GetLocation())) {
Assert(l != NULL && o != NULL && r != NULL);
(op=o)->SetParent(this);
(left=l)->SetParent(this);
(right=r)->SetParent(this);
}
CompoundExpr::CompoundExpr(Operator *o, Expr *r)
: Expr(Join(o->GetLocation(), r->GetLocation())) {
Assert(o != NULL && r != NULL);
left = NULL;
(op=o)->SetParent(this);
(right=r)->SetParent(this);
}
CompoundExpr::CompoundExpr(Expr *l, Operator *o)
: Expr(Join(l->GetLocation(), o->GetLocation())) {
Assert(l != NULL && o != NULL);
(left=l)->SetParent(this);
(op=o)->SetParent(this);
}
void CompoundExpr::PrintChildren(int indentLevel) {
if (left) left->Print(indentLevel+1);
op->Print(indentLevel+1);
if (right) right->Print(indentLevel+1);
}
ConditionalExpr::ConditionalExpr(Expr *c, Expr *t, Expr *f)
: Expr(Join(c->GetLocation(), f->GetLocation())) {
Assert(c != NULL && t != NULL && f != NULL);
(cond=c)->SetParent(this);
(trueExpr=t)->SetParent(this);
(falseExpr=f)->SetParent(this);
}
void ConditionalExpr::PrintChildren(int indentLevel) {
cond->Print(indentLevel+1, "(cond) ");
trueExpr->Print(indentLevel+1, "(true) ");
falseExpr->Print(indentLevel+1, "(false) ");
}
ArrayAccess::ArrayAccess(yyltype loc, Expr *b, Expr *s) : LValue(loc) {
(base=b)->SetParent(this);
(subscript=s)->SetParent(this);
}
void ArrayAccess::PrintChildren(int indentLevel) {
base->Print(indentLevel+1);
subscript->Print(indentLevel+1, "(subscript) ");
}
FieldAccess::FieldAccess(Expr *b, Identifier *f)
: LValue(b? Join(b->GetLocation(), f->GetLocation()) : *f->GetLocation()) {
Assert(f != NULL); // b can be be NULL (just means no explicit base)
base = b;
if (base) base->SetParent(this);
(field=f)->SetParent(this);
}
void FieldAccess::PrintChildren(int indentLevel) {
if (base) base->Print(indentLevel+1);
field->Print(indentLevel+1);
}
Call::Call(yyltype loc, Expr *b, Identifier *f, List<Expr*> *a) : Expr(loc) {
Assert(f != NULL && a != NULL); // b can be be NULL (just means no explicit base)
base = b;
if (base) base->SetParent(this);
(field=f)->SetParent(this);
(actuals=a)->SetParentAll(this);
}
void Call::PrintChildren(int indentLevel) {
if (base) base->Print(indentLevel+1);
if (field) field->Print(indentLevel+1);
if (actuals) actuals->PrintAll(indentLevel+1, "(actuals) ");
}
llvm::Value* VarExpr::Emit() {
return new llvm::LoadInst(findSymbol(id->GetName()).second, NULL, irgen.GetBasicBlock());
}
llvm::Value* AssignExpr::Emit() {
return new llvm::StoreInst(left->Emit(), right->Emit(), NULL, irgen.GetBasicBlock());
}
string Operator::getToken() const {
return tokenString;
}
llvm::Value* IntConstant::Emit() {
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(*irgen.GetContext()), value, true);
}
llvm::Value* FloatConstant::Emit() {
return llvm::ConstantInt::get(llvm::Type::getFloatTy(*irgen.GetContext()), value, true);
}
llvm::Value* BoolConstant::Emit() {
return llvm::ConstantInt::get(llvm::Type::getInt1Ty(*irgen.GetContext()), value, false);
}
llvm::Value* Call::Emit() {
vector<llvm::Value*> args;
for(int i = 0; i < actuals->NumElements(); i++) {
args.push_back(actuals->Nth(i)->Emit());
}
return llvm::CallInst::Create(findSymbol(field->GetName()).second, args, NULL, irgen.GetBasicBlock());
}
llvm::Value* CompoundExpr::Emit() {
llvm::Value* l = l ? left->Emit() : NULL;
llvm::Value* r = r ? right->Emit() : NULL;
llvm::BasicBlock* b = irgen.GetBasicBlock();
//austins additional value
llvm::Value *val;
if(!l) {
if(op->getToken() == "++")
val = llvm::ConstantInt::get(irgen.GetIntType(), 1);
return llvm::BinaryOperator::CreateAdd(l, val, "", irgen.GetBasicBlock());
if(op->getToken() == "--")
val = llvm::ConstantInt::get(irgen.GetIntType(), 1);
return llvm::BinaryOperator::CreateSub(l, val, "", irgen.GetBasicBlock());
}
if(l->getType()->isFPOrFPVectorTy()) {
if(op->getToken() == "+")
return llvm::BinaryOperator::Create(llvm::Instruction::FAdd, l, r, NULL, b);
if(op->getToken() == "-")
return llvm::BinaryOperator::Create(llvm::Instruction::FSub, l, r, NULL, b);
if(op->getToken() == "*")
return llvm::BinaryOperator::Create(llvm::Instruction::FMul, l, r, NULL, b);
if(op->getToken() == "/")
return llvm::BinaryOperator::Create(llvm::Instruction::FDiv, l, r, NULL, b);
if(op->getToken() == "==")
return llvm::CmpInst::Create(llvm::CmpInst::ICmp, llvm::CmpInst::ICMP_EQ, l, r, NULL, b);
if(op->getToken() == "!=")
return llvm::CmpInst::Create(llvm::CmpInst::ICmp, llvm::CmpInst::ICMP_NE, l, r, NULL, b);
if(op->getToken() == "<=")
return llvm::CmpInst::Create(llvm::CmpInst::ICmp, llvm::CmpInst::ICMP_SLE, l, r, NULL, b);
if(op->getToken() == ">=")
return llvm::CmpInst::Create(llvm::CmpInst::ICmp, llvm::CmpInst::ICMP_SGE, l, r, NULL, b);
if(op->getToken() == "<")
return llvm::CmpInst::Create(llvm::CmpInst::ICmp, llvm::CmpInst::ICMP_SLT, l, r, NULL, b);
if(op->getToken() == ">")
return llvm::CmpInst::Create(llvm::CmpInst::ICmp, llvm::CmpInst::ICMP_SGT, l, r, NULL, b);
}
if(l->getType()->isIntOrIntVectorTy()) {
if(op->getToken() == "+")
return llvm::BinaryOperator::Create(llvm::Instruction::Add, l, r, NULL, b);
if(op->getToken() == "-")
return llvm::BinaryOperator::Create(llvm::Instruction::Sub, l, r, NULL, b);
if(op->getToken() == "*")
return llvm::BinaryOperator::Create(llvm::Instruction::Mul, l, r, NULL, b);
if(op->getToken() == "/")
return llvm::BinaryOperator::Create(llvm::Instruction::SDiv, l, r, NULL, b);
if(op->getToken() == "==")
return llvm::CmpInst::Create(llvm::CmpInst::FCmp, llvm::CmpInst::FCMP_OEQ, l, r, NULL, b);
if(op->getToken() == "!=")
return llvm::CmpInst::Create(llvm::CmpInst::FCmp, llvm::CmpInst::FCMP_ONE, l, r, NULL, b);
if(op->getToken() == "<=")
return llvm::CmpInst::Create(llvm::CmpInst::FCmp, llvm::CmpInst::FCMP_OLE, l, r, NULL, b);
if(op->getToken() == ">=")
return llvm::CmpInst::Create(llvm::CmpInst::FCmp, llvm::CmpInst::FCMP_OGE, l, r, NULL, b);
if(op->getToken() == "<")
return llvm::CmpInst::Create(llvm::CmpInst::FCmp, llvm::CmpInst::FCMP_OLT, l, r, NULL, b);
if(op->getToken() == ">")
return llvm::CmpInst::Create(llvm::CmpInst::FCmp, llvm::CmpInst::FCMP_OGT, l, r, NULL, b);
}
if(op->getToken() == "&&") {
return llvm::BinaryOperator::Create(llvm::Instruction::And, l, r, NULL, b);
}
if(op->getToken() == "||") {
return llvm::BinaryOperator::Create(llvm::Instruction::Or, l, r, NULL, b);
}
return NULL;
}