Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2729469
compilepass.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
Fri, Mar 13, 2:09 AM
Size
25 KB
Mime Type
text/x-c++
Expires
Sun, Mar 15, 2:09 AM (8 h, 56 m)
Engine
blob
Format
Raw Data
Handle
243020
Attached To
rXR Xreate
compilepass.cpp
View Options
#include "compilepass.h"
#include "clasplayer.h"
#include <ast.h>
#include "llvmlayer.h"
#include "query/containers.h"
#include "query/context.h"
#include "compilation/containers.h"
#include "compilation/latecontextcompiler2.h"
#include "ExternLayer.h"
#include "pass/adhocpass.h"
#include "compilation/targetinterpretation.h"
#include "pass/versionspass.h"
#include "compilation/scopedecorators.h"
#include <boost/optional.hpp>
#include <memory>
#include <iostream>
using namespace std;
using namespace xreate;
using namespace xreate::compilation;
using namespace llvm;
//TODO use Scope<TargetLlvm>
//SECTIONTAG types/convert implementation
//TODO type conversion:
//a) automatically expand types int -> bigger int; int -> floating
//b) detect exact type of `num` based on max used numeral / function type
//c) warning if need to truncate (allow/dissalow based on annotations)
namespace xreate {
llvm::Value*
doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder){
if (tyTarget->isIntegerTy() && source->getType()->isIntegerTy())
{
llvm::IntegerType* tyTargetInt = llvm::dyn_cast<IntegerType>(tyTarget);
llvm::IntegerType* tySourceInt = llvm::dyn_cast<IntegerType>(source->getType());
if (tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()){
return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
}
if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
}
}
if (source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()){
return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
}
return source;
}
std::string
BasicFunctionDecorator::prepareName(){
AST* ast = FunctionUnit::pass->man->root;
string name = ast->getFunctionVariants(FunctionUnit::function->__name).size() > 1?
FunctionUnit::function->__name + std::to_string(FunctionUnit::function.id()) :
FunctionUnit::function->__name;
return name;
}
std::vector<llvm::Type*>
BasicFunctionDecorator::prepareArguments(){
LLVMLayer* llvm = FunctionUnit::pass->man->llvm;
AST* ast = FunctionUnit::pass->man->root;
CodeScope* entry = FunctionUnit::function->__entry;
std::vector<llvm::Type*> signature;
std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
[llvm, ast, entry](const std::string &arg)->llvm::Type* {
assert(entry->__identifiers.count(arg));
ScopedSymbol argid{entry->__identifiers.at(arg), VERSION_NONE};
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
});
return signature;
}
llvm::Type*
BasicFunctionDecorator::prepareResult(){
LLVMLayer* llvm = FunctionUnit::pass->man->llvm;
AST* ast = FunctionUnit::pass->man->root;
CodeScope* entry = FunctionUnit::function->__entry;
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(ScopedSymbol::RetSymbol).type));
}
llvm::Function::arg_iterator
BasicFunctionDecorator::prepareBindings(){
CodeScope* entry = FunctionUnit::function->__entry;
AbstractCodeScopeUnit* entryCompilation = FunctionUnit::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = FunctionUnit::raw->arg_begin();
for (std::string &arg : entry->__bindings) {
ScopedSymbol argid{entry->__identifiers[arg], VERSION_NONE};
entryCompilation->bindArg(&*fargsI, argid);
fargsI->setName(arg);
++fargsI;
}
return fargsI;
}
//SECTIONTAG late-context FunctionDecorator
template<class Parent>
class LateContextFunctionDecorator: public Parent{
public:
LateContextFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p), contextCompiler(this, p)
{}
protected:
std::vector<llvm::Type*> prepareArguments(){
std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
if (sizeLateContextDemand) {
llvm::Type* ty32 = llvm::Type::getInt32Ty(llvm::getGlobalContext());
llvm::Type* tyDemand = llvm::ArrayType::get(ty32, sizeLateContextDemand);
arguments.push_back(tyDemand);
}
return arguments;
}
llvm::Function::arg_iterator prepareBindings(){
llvm::Function::arg_iterator fargsI = Parent::prepareBindings();
size_t sizeLateContextDemand = contextCompiler.getFunctionDemandSize();
if (sizeLateContextDemand){
fargsI->setName("latecontext");
contextCompiler.rawContextArgument = &*fargsI;
++fargsI;
}
return fargsI;
}
public:
LateContextCompiler2 contextCompiler;
};
//SECTIONTAG adhoc FunctionDecorator
template<class Parent>
class AdhocFunctionDecorator: public Parent{
public:
AdhocFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p) {}
protected:
llvm::Type* prepareResult(){
PassManager* man = Parent::pass->man;
CodeScope* entry = Parent::function->__entry;
LLVMLayer* llvm = Parent::pass->man->llvm;
AST* ast = Parent::pass->man->root;
AdhocPass* adhocpass = reinterpret_cast<AdhocPass*>(man->getPassById(PassId::AdhocPass));
if (! Parent::function->isPrefunction){
return Parent::prepareResult();
}
adhocImplementation = adhocpass->findAssotiatedScheme(entry);
return llvm->toLLVMType(ast->expandType(adhocImplementation->getResultType()));
}
public:
AdhocScheme* adhocImplementation=nullptr;
};
//DEBT compiler rigidly depends on exact definition of DefaultFunctionUnit
typedef LateContextFunctionDecorator<
AdhocFunctionDecorator<
BasicFunctionDecorator>> DefaultFunctionUnit;
AbstractCodeScopeUnit::AbstractCodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
: pass(compilePass), function(f), scope(codeScope)
{}
llvm::Value*
CallStatementRaw::operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
llvm::Function* calleeInfo = dyn_cast<llvm::Function>(__callee);
if (calleeInfo){
auto argsFormal = calleeInfo->args();
int pos=0;
//SECTIONTAG types/convert function ret value
for (auto argFormal = argsFormal.begin(); argFormal!=argsFormal.end(); ++argFormal, ++pos){
args[pos] = doAutomaticTypeConversion(args[pos], argFormal->getType(), llvm->builder);
}
}
return llvm->builder.CreateCall(__calleeTy, __callee, args, hintDecl);
}
//DESABLEDFEATURE implement inlining
class CallStatementInline: public CallStatement{
public:
CallStatementInline(FunctionUnit* caller, FunctionUnit* callee, LLVMLayer* l)
: __caller(caller), __callee(callee), llvm(l) {}
llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
//TOTEST inlining
// CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
// for(int i=0, size = args.size(); i<size; ++i) {
// entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__bindings.at(i)));
// }
//
//
// return entryCompilation->compile();
return nullptr;
}
private:
FunctionUnit* __caller;
FunctionUnit* __callee;
LLVMLayer* llvm;
bool isInline(){
// Symbol ret = Symbol{0, function->__entry};
// bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
//TODO consider inlining
return false;
}
};
}
BasicCodeScopeUnit::BasicCodeScopeUnit(CodeScope* codeScope, FunctionUnit* f, CompilePass* compilePass)
: AbstractCodeScopeUnit(codeScope, f, compilePass)
{}
llvm::Value*
BasicCodeScopeUnit::processSymbol(const Symbol& s, std::string hintRetVar){
Expression declaration = CodeScope::getDeclaration(s);
CodeScope* scope = s.scope;
AbstractCodeScopeUnit* self = AbstractCodeScopeUnit::function->getScopeUnit(scope);
return self->process(declaration, hintRetVar);
}
//SECTIONTAG late-context find callee function
//TOTEST static late context decisions
//TOTEST dynamic late context decisions
CallStatement*
BasicCodeScopeUnit::findFunction(const std::string& calleeName){
LLVMLayer* llvm = pass->man->llvm;
ClaspLayer* clasp = pass->man->clasp;
DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
ContextQuery* queryContext = pass->queryContext;
const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionVariants(calleeName);
//if no specializations registered - check external function
if (specializations.size()==0){
llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
return new CallStatementRaw(external, llvm);
}
//no decisions required
if (specializations.size()==1){
if (!specializations.front()->guardContext.isValid()) {
return new CallStatementRaw( pass->getFunctionUnit(specializations.front())->compile(), llvm);
}
}
//TODO move dictSpecialization over to a separate function in order to perform cache, etc.
//prepare specializations dictionary
std::map<Expression, ManagedFnPtr> dictSpecializations;
boost::optional<ManagedFnPtr> variantDefault;
boost::optional<ManagedFnPtr> variant;
for(const ManagedFnPtr& f: specializations){
const Expression& guard = f->guardContext;
//default case:
if (!guard.isValid()){
variantDefault = f;
continue;
}
assert(dictSpecializations.emplace(guard, f).second && "Found several identical specializations");
}
//check static context
ScopePacked scopeCaller = clasp->pack(this->scope);
const string atomSpecialization = "specialization";
const Expression topicSpecialization(Operator::CALL, {(Atom<Identifier_t>(string(atomSpecialization))), (Atom<Identifier_t>(string(calleeName))), (Atom<Number_t>(scopeCaller))});
const Decisions& decisions = queryContext->getFinalDecisions(scopeCaller);
if (decisions.count(topicSpecialization)){
variant = dictSpecializations.at(decisions.at(topicSpecialization));
}
//TODO check only demand for this particular topic.
size_t sizeDemand = function->contextCompiler.getFunctionDemandSize();
//decision made if static context found or no late context exists(and there is default variant)
bool flagHasStaticDecision = variant || (variantDefault && !sizeDemand);
//if no late context exists
if (flagHasStaticDecision) {
FunctionUnit* calleeUnit = pass->getFunctionUnit(variant? *variant: *variantDefault);
//inlining possible based on static decision only
// if (calleeUnit->isInline()) {
// return new CallStatementInline(function, calleeUnit);
// }
return new CallStatementRaw(calleeUnit->compile(), llvm);
}
//require default variant if no static decision made
assert(variantDefault);
llvm::Function* functionVariantDefault = this->pass->getFunctionUnit(*variantDefault)->compile();
llvm::Value* resultFn = function->contextCompiler.findFunction(calleeName, functionVariantDefault, scopeCaller);
llvm::PointerType *resultPTy = cast<llvm::PointerType>(resultFn->getType());
llvm::FunctionType *resultFTy = cast<llvm::FunctionType>(resultPTy->getElementType());
return new CallStatementRaw(resultFn, resultFTy, llvm);
}
//DISABLEDFEATURE transformations
// if (pass->transformations->isAcceptable(expr)){
// return pass->transformations->transform(expr, result, ctx);
// }
llvm::Value*
BasicCodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl){
#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left; llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
xreate::compilation::Advanced instructions = xreate::compilation::Advanced({this, function, pass});
switch (expr.op) {
case Operator::ADD: case Operator::SUB: case Operator::MUL:
case Operator::DIV: case Operator::EQU: case Operator::LSS:
case Operator::GTR: case Operator::NE: case Operator::LSE:
case Operator::GTE:
assert(expr.__state == Expression::COMPOUND);
assert(expr.operands.size() == 2);
left = process(expr.operands[0]);
right = process(expr.operands[1]);
//SECTIONTAG types/convert binary operation
right = doAutomaticTypeConversion(right, left->getType(), l.builder);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
break;
case Operator::SUB:
return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU:
if (left->getType()->isIntegerTy()) return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
if (left->getType()->isFloatingPointTy()) return l.builder.CreateFCmpOEQ(left, right, DEFAULT("tmp_equ"));
break;
case Operator::NE:
return l.builder.CreateICmpNE(left, right, DEFAULT("tmp_ne"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
break;
case Operator::LSE:
return l.builder.CreateICmpSLE(left, right, DEFAULT("tmp_lse"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
break;
case Operator::GTE:
return l.builder.CreateICmpSGE(left, right, DEFAULT("tmp_gte"));
break;
case Operator::NEG:
left = process(expr.operands[0]);
return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
break;
case Operator::CALL: {
assert(expr.__state == Expression::COMPOUND);
std::string nameCallee = expr.getValueString();
shared_ptr<CallStatement> callee(findFunction(nameCallee));
//prepare arguments
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size());
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[this](const Expression &operand) {
return process(operand);
}
);
ScopePacked outerScopeId = pass->man->clasp->pack(this->scope);
//TASK a) refactor CALL/ADHOC/find function
//SECTIONTAG late-context propagation arg
size_t calleeDemandSize = pass->queryContext->getFunctionDemand(nameCallee).size();
if (calleeDemandSize){
DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
llvm::Value* argLateContext = function->contextCompiler.compileContextArgument(nameCallee, outerScopeId);
args.push_back(argLateContext);
}
return (*callee)(move(args), DEFAULT("res_"+nameCallee));
}
case Operator::IF:
{
return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOOP_CONTEXT:
{
assert(false);
return nullptr;
//return instructions.compileLoopContext(expr, DEFAULT("tmp_loop"));
}
case Operator::LOGIC_AND: {
assert(expr.operands.size() == 1);
return process (expr.operands[0]);
}
case Operator::LIST:
{
return instructions.compileListAsSolidArray(expr, DEFAULT("tmp_list"));
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::LIST_NAMED:
{
typedef Expanded<TypeAnnotation> ExpandedType;
ExpandedType tyRaw = l.ast->expandType(expr.type);
const std::vector<string> fields = (tyRaw.get().__operator == TypeOperator::CUSTOM)?
l.layerExtern->getStructFields(l.layerExtern->lookupType(tyRaw.get().__valueCustom))
: tyRaw.get().fields;
std::map<std::string, size_t> indexFields;
for(size_t i=0, size = fields.size(); i<size; ++i){
indexFields.emplace(fields[i], i);
}
llvm::StructType* tyRecord = llvm::cast<llvm::StructType>(l.toLLVMType(tyRaw));
llvm::Value* record = llvm::UndefValue::get(tyRecord);
for (size_t i=0; i<expr.operands.size(); ++i){
const Expression& operand = expr.operands.at(i);
unsigned int fieldId = indexFields.at(expr.bindings.at(i));
llvm::Value* result = 0;
//TODO Null ad hoc Llvm implementation
// if (operand.isNone()){
// llvm::Type* tyNullField = tyRecord->getElementType(fieldId);
// result = llvm::UndefValue::get(tyNullField);
//
// } else {
result = process(operand);
// }
assert (result);
record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
}
return record;
};
case Operator::MAP:
{
assert(expr.blocks.size());
return instructions.compileMapSolidOutput(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, DEFAULT("fold"));
};
case Operator::FOLD_INF:
{
return instructions.compileFoldInf(expr, DEFAULT("fold"));
};
case Operator::INDEX:
{
//TODO allow multiindex
assert(expr.operands.size()==2);
assert(expr.operands[0].__state == Expression::IDENT);
const std::string& hintIdent= expr.operands[0].getValueString();
Symbol s = Attachments::get<Symbol>(expr.operands[0]);
const ExpandedType& t2 = pass->man->root->expandType(CodeScope::getDeclaration(s).type);
llvm::Value* aggr = processSymbol(s, hintIdent);
switch (t2.get().__operator)
{
case TypeOperator::STRUCT: case TypeOperator::CUSTOM:
{
const Expression& idx = expr.operands.at(1);
assert(idx.__state == Expression::STRING);
std::string idxField = idx.getValueString();
return instructions.compileStructIndex(aggr, t2, idxField);
};
case TypeOperator::ARRAY: {
std::vector<llvm::Value*> indexes;
std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this] (const Expression& op){
return process(op);
}
);
return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + hintIdent));
};
default:
assert(false);
}
};
//SECTIONTAG adhoc actual compilation
//TODO a) make sure that it's correct: function->adhocImplementation built for Entry scope and used in another scope
case Operator::ADHOC: {
DefaultFunctionUnit* function = dynamic_cast<DefaultFunctionUnit*>(this->function);
assert(function->adhocImplementation && "Adhoc implementation not found");
const Expression& comm = AdhocExpression(expr).getCommand();
CodeScope* scope = function->adhocImplementation->getCommandImplementation(comm);
AbstractCodeScopeUnit* unitScope = function->getScopeUnit(scope);
//SECTIONTAG types/convert ADHOC ret convertation
llvm::Type* resultTy = l.toLLVMType( pass->man->root->expandType(function->adhocImplementation->getResultType()));
return doAutomaticTypeConversion(unitScope->compile(), resultTy, l.builder);
};
case Operator::CALL_INTRINSIC:{
const std::string op = expr.getValueString();
if (op == "copy") {
llvm::Value* result = process(expr.getOperands().at(0));
auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
decoratorVersions->processIntrinsicCopy(result, storage);
return l.builder.CreateLoad(storage, hintVarDecl);
}
assert(false && "undefined intrinsic");
}
case Operator::NONE:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT: {
Symbol s = Attachments::get<Symbol>(expr);
return processSymbol(s, expr.getValueString());
}
case Expression::NUMBER: {
llvm::Type* typConst;
if (expr.type.isValid()){
typConst = l.toLLVMType(pass->man->root->expandType(expr.type));
} else {
typConst = llvm::Type::getInt32Ty(llvm::getGlobalContext());
}
int literal = expr.getValueDouble();
return llvm::ConstantInt::get(typConst, literal);
}
case Expression::STRING: {
return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
case Expression::VARIANT: {
const ExpandedType& typVariant = pass->man->root->expandType(expr.type);
llvm::Type* typRaw = l.toLLVMType(typVariant);
int value = expr.getValueDouble();
return llvm::ConstantInt::get(typRaw, value);
}
default: {
break;
}
};
break;
default: break;
}
assert(false);
return 0;
}
llvm::Value*
BasicCodeScopeUnit::compile(const std::string& hintBlockDecl){
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm::getGlobalContext(), hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
Symbol symbScope = Symbol{ScopedSymbol::RetSymbol, scope};
return processSymbol(symbScope);
}
llvm::Function*
FunctionUnit::compile(){
if (raw != nullptr) return raw;
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
string&& functionName = prepareName();
std::vector<llvm::Type*>&& types = prepareArguments();
llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
prepareBindings();
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
llvm::Value* result =getScopeUnit(function->__entry)->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
builder.CreateRet(doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
if (blockCurrent){
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
AbstractCodeScopeUnit*
FunctionUnit::getScopeUnit(CodeScope* scope){
if (!scopes.count(scope)){
AbstractCodeScopeUnit* unit = new DefaultScopeUnit(scope, this, pass);
scopes.emplace(scope, std::unique_ptr<AbstractCodeScopeUnit>(unit));
}
return scopes.at(scope).get();
}
AbstractCodeScopeUnit*
FunctionUnit::getEntry(){
return getScopeUnit(function->getEntryScope());
}
AbstractCodeScopeUnit*
FunctionUnit::getScopeUnit(ManagedScpPtr scope){
return getScopeUnit(&*scope);
}
FunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function){
unsigned int id = function.id();
if (!functions.count(id)){
FunctionUnit* unit = new DefaultFunctionUnit(function, this);
functions.emplace(id, unit);
return unit;
}
return functions.at(id);
}
void
CompilePass::run(){
managerTransformations = new TransformationsManager();
targetInterpretation = new TargetInterpretation(this->man->root, this);
queryContext = reinterpret_cast<ContextQuery*> (man->clasp->getQuery(QueryId::ContextQuery));
//Find out main function;
ClaspLayer::ModelFragment model = man->clasp->query(Config::get("function-entry"));
assert(model && "Error: No entry function found");
assert(model->first != model->second && "Error: Ambiguous entry function");
string nameMain = std::get<0>(ClaspLayer::parse<std::string>(model->first->second));
FunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction(){
assert(entry);
return entry;
}
void
CompilePass::prepareQueries(ClaspLayer* clasp){
clasp->registerQuery(new containers::Query(), QueryId::ContainersQuery);
clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
}
Event Timeline
Log In to Comment