ast.cpp
No OneTemporary

File Metadata

Created
Wed, Jul 8, 8:55 AM
#include "ast.h"
#include <stdexcept>
using namespace std;
TypeAnnotation::TypeAnnotation()
{}
TypeAnnotation::TypeAnnotation(const Atom<Type_t> &typ)
{
__value = typ.get();
}
TypeAnnotation::TypeAnnotation(const TypeOperator &op, const TypeAnnotation &typ)
{}
llvm::Type*
TypeAnnotation::toLLVMType()
{
switch (__value)
{
case Bool:
return llvm::Type::getInt1Ty(llvm::getGlobalContext());
case Int:
case Float:
case Num:
return llvm::Type::getDoubleTy(llvm::getGlobalContext());
default:
assert(false);
}
return NULL;
}
Expression::Expression()
: __op(Operator::NONE), state(INVALID)
{}
Expression::Expression(const Atom<Number_t>& number)
: state(NUMBER), __op(Operator::NONE), __valueD(number.get())
{
}
Expression::Expression(const Atom<Identifier_t> &ident)
: state(IDENT), __op(Operator::NONE), __valueS(ident.get())
{
}
Expression::Expression(const Operator &op, const Expression &arg)
: state(COMPOUND), __op(op)
{
operands.push_back(arg);
}
void
Expression::addArg(const Expression &arg)
{
assert(state == COMPOUND);
assert(op!=Operator::NONE);
operands.push_back(arg);
}
llvm::Value*
Expression::compile(LLVMLayer& l, Function* f, std::string* retVarHint)
{
std::string var;
if (retVarHint && f->__vartable.count(*retVarHint))
{
var = *retVarHint;
}
#define VARNAME(x) (var.size()? var : x)
llvm::Value* left; llvm::Value* right;
switch (__op)
{
case Operator::ADD: case Operator::SUB: case Operator::MUL: case Operator::DIV: case Operator::EQU: case Operator::LSS: case Operator::GTR:
left = operands[0].compile(l, f);
right = operands[1].compile(l, f);
break;
default: ;
}
switch (__op)
{
case Operator::ADD:
return l.builder.CreateFAdd(left, right, VARNAME("tmp_add"));
break;
case Operator::SUB:
return l.builder.CreateFSub(left, right, VARNAME("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateFMul(left, right, VARNAME("tmp_add"));
break;
case Operator::DIV:
return l.builder.CreateFDiv(left, right, VARNAME("tmp_sub"));
break;
case Operator::EQU:
return l.builder.CreateFCmpOEQ(left, right, VARNAME("tmp_eq"));
break;
case Operator::LSS:
return l.builder.CreateFCmpOLT(left, right, VARNAME("tmp_eq"));
break;
case Operator::GTR:
return l.builder.CreateFCmpOGT(left, right, VARNAME("tmp_eq"));
break;
case Operator::NEG:
left = operands[0].compile(l, f);
return l.builder.CreateFNeg(left, VARNAME("tmp_eq"));
break;
case Operator::CALL:
{
std::string fname = operands[0].__valueS;
assert(f->root->__rawFunctions.count(fname));
llvm::Function* callee = f->root->__rawFunctions[fname];
std::vector<llvm::Value*> args;
args.reserve(operands.size()-1);
for(int i=1; i<operands.size(); ++i)
{
args.push_back(operands[i].compile(l, f));
}
return l.builder.CreateCall(callee, args, VARNAME("tmp_call"));
}
break;
case Operator::NONE:
switch (state)
{
case IDENT:
{
std::string vname = operands[0].__valueS;
assert(f->__vartable.count(vname));
vid vId =f->__vartable[vname];
assert(var.size()==0);
if (f->__rawVars.count(vId))
{
return f->__rawVars[vId];
}
Expression& e = f->__declarations[vId];
llvm::Value* result = e.compile(l, f);
f->__rawVars[vId] = result;
return result;
break;
}
case NUMBER:
double literal = operands[0].__valueD;
return llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(literal));
};
break;
}
assert(false);
return 0;
}
AST::AST()
{
}
std::string
AST::getModuleName()
{
const std::string name = "moduleTest";
return name;
}
void
AST::compile(LLVMLayer &layer)
{
layer.module = new llvm::Module(getModuleName(),llvm::getGlobalContext());
for(Function& f: __functions)
{
llvm::Function* rawf = f.compile(layer);
__rawFunctions[f.getName()] = rawf;
}
}
void
AST::run(LLVMLayer &l)
{
llvm::PassManager PM;
PM.add(llvm::createPrintModulePass(&llvm::outs()));
PM.run(*l.module);
}
Function::Function(const wstring &name)
{
char buffer[1000];
wcstombs(buffer, name.c_str(), 1000);
__name = buffer;
}
void
Function::addArg(const wstring &vname, const TypeAnnotation &typ)
{
char buffer[1000];
wcstombs(buffer, vname.c_str(), 1000);
std::string name(buffer);
vid id = registerVar(name);
__definitions[id] = typ;
__args.push_back(name);
}
void
Function::setBody(const Expression &body)
{
__body = body;
}
void
Function::setReturnType(const TypeAnnotation &rtyp)
{
__retType = rtyp;
}
vid
Function::registerVar(const std::string& vname)
{
return ++__vCounter;
}
const std::string&
Function::getName() const
{
return __name;
}
void
Function::addListDeclaration(const wstring &vname, const TypeAnnotation &typ, const Expression &e)
{}
void
Function::addDeclaration(const wstring &vname, const TypeAnnotation &typ, const Expression &e)
{
char buffer[1000];
wcstombs(buffer, vname.c_str(), 1000);
std::string v(buffer);
vid id = registerVar(v);
__definitions[id] = typ;
__declarations[id] = e;
}
llvm::Function*
Function::compile(LLVMLayer &l)
{
std::vector<llvm::Type*> types;
std::transform(__args.begin(), __args.end(), std::inserter(types, types.end()),
[this](std::string& arg) {
assert(__vartable.count(arg));
vid argid = __vartable[arg];
assert(__definitions.count(argid));
return __definitions[argid].toLLVMType();
} );
llvm::FunctionType* ft = llvm::FunctionType::get(__retType.toLLVMType(), types,false);
__raw = llvm::cast<llvm::Function>(l.module->getOrInsertFunction(__name,ft));
llvm::Function::arg_iterator fargsI = __raw->arg_begin();
for(std::string& arg : __args)
{
vid argid = __vartable[arg];
__rawVars[argid] = fargsI;
fargsI->setName(arg);
++fargsI;
}
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", __raw);
l.builder.SetInsertPoint(block);
l.builder.CreateRet(__body.compile(l, this, 0));
l.moveToGarbage(ft);
return __raw;
};

Event Timeline