ast-compilation.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 1:47 AM

ast-compilation.cpp

#include <ast.h>
#include "codeinstructions.h"
using namespace xreate;
llvm::Value *
CodeScope::compileExpression(const Expression &expr, LLVMLayer &l, const std::string * const hintRetVar) {
#define VARNAME(x) (hintRetVar==0 ? 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->getType()->dump();
right->getType()->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;
assert(l.ast->__indexFunctions.count(fname));
const Function &calleeFunc = l.ast->getFunctionById(l.ast->__indexFunctions[fname]);
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 CodeInstruction<Operator::LIST>(expr, l).compile(hintRetVar);
};
case Operator::INDEX:
{
assert(expr.operands.size());
const std::string &name = expr.__valueS;
llvm::Value* heap = findSymbol(name, l);
std::vector<llvm::Value*> indexes;
indexes.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0));
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this, &l] (const Expression& op){return compileExpression(op, l);}
);
llvm::Value* result = l.builder.CreateGEP(heap, llvm::ArrayRef<llvm::Value*>(indexes), VARNAME("tmp_el_of_arr"));
result->getType()->dump();
return result;
};
case Operator::NONE:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT: {
const std::string &vname = expr.__valueS;
return findSymbol(vname, l);
}
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 * const hintBlockName) {
if (hintBlockName) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), *hintBlockName, l.function);
l.builder.SetInsertPoint(block);
}
return compileExpression(__body, l, 0);
}
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(__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 : __entry.__args) {
VID argid = __entry.__vartable[arg];
__entry.__rawVars[argid] = fargsI;
fargsI->setName(arg);
++fargsI;
}
l.function = __raw;
const std::string blockName = "entry";
l.builder.CreateRet(__entry.compile(l, &blockName));
l.function = nullptr;
l.moveToGarbage(ft);
return __raw;
};
void
AST::compile(LLVMLayer &layer) {
layer.ast = this;
layer.module = new llvm::Module(getModuleName(), llvm::getGlobalContext());
int __debug_fcount = __functions.size();
for (Function &f: __functions) {
llvm::Function *rawf = f.compile(layer);
}
}

Event Timeline