Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3995790
latecontextcompiler2.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, 3:34 AM
Size
8 KB
Mime Type
text/x-c++
Expires
Fri, Jul 10, 3:34 AM (1 d, 15 h)
Engine
blob
Format
Raw Data
Handle
271752
Attached To
rXR Xreate
latecontextcompiler2.cpp
View Options
/*
* LateContextCompiler2.cpp
*
* Created on: 10 февр. 2016
* Author: pgess
*/
//TOTEST default variants - do not enable specialization context in order to check default variant invocation
#include "latecontextcompiler2.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include "query/context.h"
#include <iostream>
using namespace std;
namespace xreate {
const string topicSpecializationAtom = "specialization";
const string topicDependencyAtom = "dependency";
typedef ExpressionSerialization<RequirementIntegralCode>::Code DomainId;
typedef ExpressionSerialization<RequirementIntegralCode>::Serializer Domain;
//TODO implement variantDefault;
llvm::Value* compileDecisionSelector(llvm::IRBuilder<>& builder, llvm::Value* selector, std::vector<llvm::Value*> vectorVariants, llvm::Value* variantDefault=nullptr){
assert(vectorVariants.size()>0);
llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::Type* tyElement = vectorVariants[0]->getType();
llvm::Type* tyVariants = llvm::VectorType::get(tyElement, vectorVariants.size());
llvm::Value* vectorRaw = llvm::ConstantVector::getNullValue(tyVariants);
for(DomainId i=0; i<vectorVariants.size(); ++i){
vectorRaw = builder.CreateInsertElement(vectorRaw, vectorVariants[i], llvm::ConstantInt::get(ty32, i));
}
return builder.CreateExtractElement(vectorRaw, selector);
}
LateContextCompiler2::LateContextCompiler2(compilation::FunctionUnit* f, CompilePass* p)
: function(f), pass(p){
ContextQuery* context = pass->queryContext;
__sizeOfDemand = context->getFunctionDemand(function->function->getName()).size();
}
llvm::Value*
LateContextCompiler2::findFunction(const std::string& calleeName, llvm::Function* specializationDefault, ScopePacked scopeCaller){
const string& functionName = function->function->getName();
ContextQuery* context = pass->queryContext;
llvm::IRBuilder<>& builder = pass->man->llvm->builder;
const FunctionDemand& demand = context->getFunctionDemand(functionName);
const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
//independent decision:
Expression topic(Operator::CALL, {(Atom<Identifier_t>(string(topicSpecializationAtom))), (Atom<Identifier_t>(string(calleeName))), (Atom<Number_t>(scopeCaller))});
assert(demand.right.count(topic) && "Can't determine specialization for the function");
size_t topicId = demand.right.at(topic);
llvm::Value* topicDecisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicId});
const Domain& specializationsDomain= context->getTopicDomain(topic);
std::vector<llvm::Function*> vectorVariants;
vectorVariants.reserve(specializationsDomain.size());
for (const ManagedFnPtr& f: specializations){
if (!f->guardContext.isValid()) continue;
const auto& variantId = specializationsDomain.getIdOptional(f->guardContext);
if (variantId){
if (vectorVariants.size() < *variantId + 1) {
vectorVariants.resize(*variantId + 1);
}
vectorVariants[*variantId] = pass->getFunctionUnit(f)->compile();
}
}
return compileDecisionSelectorAsSwitch(topicDecisionRaw, vectorVariants, specializationDefault);
}
llvm::Value*
LateContextCompiler2::compileContextArgument(const std::string& callee, ScopePacked scopeCaller){
const std::string& atomDependentDecision = Config::get("clasp.context.decisions.dependent");
llvm::IRBuilder<>& builder = pass->man->llvm->builder;
ContextQuery* context = pass->queryContext;
const string& functionName = function->function->getName();
const Decisions& dictStaticDecisions = context->getFinalDecisions(scopeCaller);
const FunctionDemand& demandCallee = context->getFunctionDemand(callee);
const FunctionDemand& demandSelf = context->getFunctionDemand(functionName);
llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::Type* tyDemand = llvm::ArrayType::get(ty32, demandCallee.size());
//builder.CreateAlloca(tyDemand, llvm::ConstantInt::get(ty32, 1));
llvm::Value* res = llvm::ConstantArray::getNullValue(tyDemand);
for (size_t i=0, size = demandCallee.size(); i<size; ++i){
const Expression& topic = demandCallee.left.at(i);
llvm::Value* decisionRaw;
if (demandSelf.right.count(topic)){
//TOTEST decision propagation
//propagate decision
const size_t& topicId = demandSelf.right.at(topic);
decisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicId});
} else if (dictStaticDecisions.count(topic)){
//static final decision:
const Expression& decision = dictStaticDecisions.at(topic);
const Domain& domainOfTopic = context->getTopicDomain(topic);
const DomainId& decisionCode = domainOfTopic.getId(decision);
decisionRaw = llvm::ConstantInt::get(ty32, decisionCode);
} else {
//dependent decision
decisionRaw = compileDependentDecision(topic, scopeCaller);
}
res = builder.CreateInsertValue(res, decisionRaw, llvm::ArrayRef<unsigned>{(unsigned) i});
}
return res;
}
llvm::Value*
LateContextCompiler2::compileDependentDecision(const Expression& topic, ScopePacked scopeCaller){
const string& functionName = function->function->getName();
ContextQuery* context = pass->queryContext;
llvm::IRBuilder<>& builder = pass->man->llvm->builder;
llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
const FunctionDemand& demandSelf = context->getFunctionDemand(functionName);
const Expression topicDependency = Expression(Operator::CALL, {Atom<Identifier_t>(string(topicDependencyAtom)), topic, Atom<Number_t>(scopeCaller)});
const Domain& demandOfTopic = context->getTopicDomain(topic);
const Domain& domainOfTopicDependency = context->getTopicDomain(topicDependency);
//dependent decision
vector<llvm::Value*> vectorDecisions(domainOfTopicDependency.size(), llvm::UndefValue::get(ty32));
for (const std::pair<Expression, Expression>& entry: context->getDependentDecision(scopeCaller,topic)){
vectorDecisions[domainOfTopicDependency.getId(entry.first)]= llvm::ConstantInt::get(ty32, demandOfTopic.getId(entry.second));
}
size_t topicDependencyId = demandSelf.right.at(topicDependency);
llvm::Value* decisionRaw = builder.CreateExtractValue(this->rawContextArgument, llvm::ArrayRef<unsigned>{(unsigned) topicDependencyId});
auto result = compileDecisionSelector(pass->man->llvm->builder, decisionRaw, vectorDecisions);
return result;
}
llvm::Value*
LateContextCompiler2::compileDecisionSelectorAsSwitch(llvm::Value* selector, std::vector<llvm::Function*> vectorVariants, llvm::Function* variantDefault){
llvm::IRBuilder<>& builder = pass->man->llvm->builder;
llvm::IntegerType* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::BasicBlock* blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", this->function->raw);
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "VariantDeterminationEnd", this->function->raw);
llvm::SwitchInst* instrSwitch = builder.CreateSwitch(selector, blockDefault, vectorVariants.size());
builder.SetInsertPoint(blockEpilog);
llvm::PHINode *result = builder.CreatePHI(variantDefault->getType(), vectorVariants.size(), "callee");
for (size_t i=0; i<vectorVariants.size(); ++i){
llvm::BasicBlock* blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "", this->function->raw);
builder.SetInsertPoint(blockCase);
builder.CreateBr(blockEpilog);
result->addIncoming(vectorVariants[i], blockCase);
instrSwitch->addCase(llvm::ConstantInt::get(ty32, i), blockCase);
}
builder.SetInsertPoint(blockDefault);
builder.CreateBr(blockEpilog);
result->addIncoming(variantDefault, blockDefault);
builder.SetInsertPoint(blockEpilog);
return result;
}
size_t
LateContextCompiler2::getFunctionDemandSize() const {
return __sizeOfDemand;
}
} /* namespace xreate */
Event Timeline
Log In to Comment