ast-compilation.cpp
No OneTemporary

File Metadata

Created
Mon, Aug 24, 10:57 AM

ast-compilation.cpp

#include <ast.h>
#include <iostream>
#include "query/containers.h"
#include "instructions/instr-containers.h"
using namespace xreate;
using namespace std;
llvm::Value *
CodeScope::compileExpression(const Expression &expr, LLVMLayer &l, std::string hintRetVar) {
#define VARNAME(x) (hintRetVar.empty()? x: hintRetVar)
llvm::Value *left;
llvm::Value *right;
switch (expr.op) {
case Operator::ADD:
case Operator::SUB:
case Operator::MUL:
case Operator::DIV:
case Operator::EQU:
case Operator::LSS:
case Operator::GTR:
assert(expr.__state == Expression::COMPOUND);
assert(expr.operands.size() == 2);
left = compileExpression(expr.operands[0], l);
right = compileExpression(expr.operands[1], l);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
return l.builder.CreateAdd(left, right, VARNAME("tmp_add"));
break;
case Operator::SUB:
return l.builder.CreateSub(left, right, VARNAME("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, VARNAME("tmp_mul"));
break;
case Operator::DIV:
return l.builder.CreateSDiv(left, right, VARNAME("tmp_div"));
break;
case Operator::EQU:
left->dump();
right->dump();
return l.builder.CreateICmpEQ(left, right, VARNAME("tmp_equ"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, VARNAME("tmp_lss"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, VARNAME("tmp_gtr"));
break;
case Operator::NEG:
left = compileExpression(expr.operands[0], l);
return l.builder.CreateNeg(left, VARNAME("tmp_neg"));
break;
case Operator::CALL: {
assert(expr.__state == Expression::COMPOUND);
const std::string &fname = expr.__valueS;
ManagedFnPtr calleeFunc = l.ast->findFunction(fname);
assert(calleeFunc.isValid());
llvm::Function *callee = calleeFunc->__raw;
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size() - 1);
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[&l, this](const Expression &operand) {
return compileExpression(operand, l);
}
);
return l.builder.CreateCall(callee, args, VARNAME("tmp_call"));
}
case Operator::LIST:
{
return containers::Instructions(this, &l).compileConstantArray(expr, VARNAME("list"));
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::MAP:
{
assert(expr.blocks.size());
return containers::Instructions(this, &l).compileMapArray(expr, VARNAME("map"));
};
case Operator::FOLD:
{
return containers::Instructions(this, &l).compileFold(expr, VARNAME("fold"));
};
case Operator::INDEX:
{
assert(expr.operands.size());
const std::string &ident = expr.operands.begin()->getValueString();
Symbol s = findSymbol(ident, l, true);
std::vector<llvm::Value*> indexes;
std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this, &l] (const Expression& op){return compileExpression(op, l);}
);
return containers::Instructions(this, &l).compileIndex(s, indexes, VARNAME(string("el_") + ident));
};
case Operator::NONE:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT: {
const std::string &vname = expr.__valueS;
const Symbol& var = findSymbol(vname, l, true);
return var.scope->__rawVars.at(var.identifier);
}
case Expression::NUMBER:
int literal = expr.__valueD;
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), literal);
};
break;
}
assert(false);
return 0;
}
llvm::Value *
CodeScope::compile(LLVMLayer &l, const std::string& hintBlockName) {
if (!hintBlockName.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockName, l.context.function);
l.builder.SetInsertPoint(block);
}
return compileExpression(__body, l);
}
llvm::Function *
Function::compile(LLVMLayer &l) {
std::vector<llvm::Type *> types;
std::transform(__entry->__args.begin(), __entry->__args.end(), std::inserter(types, types.end()),
[this](const std::string &arg)->llvm::Type* {
assert(__entry->__vartable.count(arg));
VID argid = __entry->__vartable.at(arg);
assert(__entry->__definitions.count(argid));
return __entry->__definitions.at(argid).toLLVMType();
});
llvm::FunctionType *ft = llvm::FunctionType::get(__entry->__definitions[0].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 : __entry->__args) {
VID argid = __entry->__vartable[arg];
__entry->__rawVars[argid] = fargsI;
fargsI->setName(arg);
++fargsI;
}
l.context.function = __raw;
const std::string blockName = "entry";
l.builder.CreateRet(__entry->compile(l, blockName));
l.context.function = nullptr;
l.moveToGarbage(ft);
return __raw;
};
void
AST::compile(LLVMLayer &layer) {
layer.ast = this;
layer.module = new llvm::Module(getModuleName(), llvm::getGlobalContext());
for (Function* f: __functions) {
llvm::Function *rawf = f->compile(layer);
}
}

Event Timeline