latecontext.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 7:58 AM

latecontext.cpp

/*
* LateContext.cpp
*
* Created on: Jan 8, 2016
* Author: pgess
*/
#include "pass/compilepass.h"
#include "compilation/latecontext.h"
#include "query/context.h"
#include "llvmlayer.h"
namespace xreate {
LateContext::LateContext(const std::string& function, CompilePass* compilePass)
: pass(compilePass), domain(&compilePass->queryContext->getFunctionDomain(function))
{}
LateContext::~LateContext()
{}
llvm::Value*
LateContext::compileCheckContext(const Expression& e){
// llvm::Value* environment;
// LLVMLayer* llvm;
//
// PackedExpression rep = __context.pack(e);
// assert(storage.count(rep));
//
// size_t id = storage.at(rep);
// //TODO determine short name of expression
// return llvm->builder.CreateExtractElement(environment, id, NAME("checkContext"+e.getValueString()));
return nullptr;
}
llvm::Value*
LateContext::findFunction(const std::string name, ScopePacked scopeOuter, llvm::Function* functionOuter){
LLVMLayer* llvm = pass->man->llvm;
ContextQuery* queryContext = pass->queryContext;
const FunctionSpecializations& specializations = queryContext->getFunctionSpecializations(name);
//check external function
if (!specializations.size()){
return nullptr;
}
const std::list<Expression>& context = queryContext->getContext(scopeOuter);
boost::optional<ManagedFnPtr> variant;
for(const Expression& c: context){
if (specializations.count(c)){
assert(!variant);
variant = specializations.at(c);
}
}
if (variant) {
return pass->getFunctionUnit(*variant)->compile();// RETURN compiled function unit
}
//require default variant if no appropriate static context exists
assert(specializations.count(Expression()));
llvm::Value* funcDefault = pass->getFunctionUnit(specializations.at(Expression()))->compile();
//choose default variant if no late context exists
if (!domain->size()) {
return funcDefault;
}
//RUNTIME PART
llvm::BasicBlock *blockCurrent = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockEnd = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ContextDeterminationEnd", functionOuter);
llvm->builder.SetInsertPoint(blockEnd);
llvm::Type* tyFuncCallee = funcDefault->getType();
llvm::PHINode *ret = llvm->builder.CreatePHI(tyFuncCallee, domain->size(), "callee");
//check runtime context
for (const Expression& c: *domain){
if (specializations.count(c)){
///if (domain[c]) return specialization.at(c) else
llvm->builder.SetInsertPoint(blockCurrent);
llvm::Value* cond;
llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ContextDeterminationNext", functionOuter);
llvm->builder.CreateCondBr(cond, blockEnd, blockNext);
ret->addIncoming(pass->getFunctionUnit(specializations.at(c))->compile(), blockCurrent);
blockCurrent = blockNext;
}
}
//check default variant in runtime
llvm->builder.SetInsertPoint(blockCurrent);
llvm->builder.CreateBr(blockEnd);
ret->addIncoming(funcDefault, blockCurrent);
llvm->builder.SetInsertPoint(blockEnd);
return ret;
}
llvm::Value*
LateContext::compileArgument(const std::string& callee, ScopePacked scopeOuter){
LLVMLayer* llvm = pass->man->llvm;
std::unordered_set<size_t> indexContextStatic;
list<Expression> listContextStatic = pass->queryContext->getContext(scopeOuter);
const ContextDomain* calleeDomain = &pass->queryContext->getFunctionDomain(callee);
llvm::Type* tyBool = llvm::Type::getInt1Ty(llvm::getGlobalContext());
llvm::Type* tyInt32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::Value* result = llvm->builder.CreateAlloca(tyBool, llvm::ConstantInt::get(tyInt32, calleeDomain->size()));
llvm::Value* valueTrue = llvm::ConstantInt::get(tyBool, 1);
llvm::Value* valueFalse = llvm::ConstantInt::get(tyBool, 0);
for (const Expression& e: listContextStatic){
auto i = calleeDomain->getExpressionId(e);
if (i){
result = llvm->builder.CreateInsertElement(result, llvm::ConstantInt::get(tyInt32, *i), valueTrue);
indexContextStatic.insert(*i);
}
}
for (size_t i=0, size=calleeDomain->size(); i<size; ++i){
const Expression& e = calleeDomain->get(i);
if (indexContextStatic.count(i))
continue;
auto posPrev = domain->getExpressionId(e);
if (posPrev){
llvm::Value* element = llvm->builder.CreateExtractElement(raw, llvm::ConstantInt::get(tyInt32, *posPrev));
result = llvm->builder.CreateInsertElement(result, llvm::ConstantInt::get(tyInt32, i), element);
continue;
}
result = llvm->builder.CreateInsertElement(result, llvm::ConstantInt::get(tyInt32, i), valueFalse);
}
return result;
}
//void
//LateContext::set(const Expression& e){
// PackedExpression representation = __context.pack(e);
//
// assert(__context.count(representation) == 0);
// __context.emplace(move(representation), __context.size());
//}
} /* namespace xreate */

Event Timeline