Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3996138
ast.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Jul 8, 8:55 AM
Size
6 KB
Mime Type
text/x-c++
Expires
Fri, Jul 10, 8:55 AM (1 d, 11 h)
Engine
blob
Format
Raw Data
Handle
271958
Attached To
rXR Xreate
ast.cpp
View Options
#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
Log In to Comment