latereasoning.cpp
No OneTemporary

File Metadata

Created
Tue, Aug 25, 10:22 AM

latereasoning.cpp

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* latereasoning.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on May 26, 2018, 3:54 PM
*/
#include "compilation/latereasoning.h"
#include "aux/latereasoning.h"
#include "compilation/scopedecorators.h"
#include "analysis/typeinference.h"
#include <vector>
using namespace xreate::compilation;
using namespace std;
namespace xreate{ namespace latereasoning {
llvm::Value*
LateReasoningCompiler::compile(const Expression& expr, const std::string& identHint){
#define HINT(x) (identHint.empty()? x : identHint)
LLVMLayer* llvm = context.pass->man->llvm;
compilation::ICodeScopeUnit* scope = context.scope;
AST* root = context.pass->man->root;
llvm::IRBuilder<>& builder = llvm->builder;
compilation::IFunctionUnit* function = context.function;
llvm::Type* typI8= llvm::Type::getInt8Ty(llvm->llvmContext);
CodeScope* scopeBody = expr.blocks.front();
Symbol guardS = Symbol{scopeBody->getSymbol(expr.bindings.front()), scopeBody};
const ExpandedType& typCondition = root->getType(expr.operands.at(0));
vector<Expression> guardVariants = typeinference::getSlaveVariants(typCondition, context.pass->man->transcend);
const int countVariants = guardVariants.size();
assert(countVariants);
llvm::Value * conditionRaw = scope->process(expr.operands.at(0));
llvm::Value* variantRaw = builder.CreateExtractValue(conditionRaw, llvm::ArrayRef<unsigned>({0}));
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(variantRaw, nullptr, countVariants);
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchLateAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(expr));
llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countVariants, HINT("switchLate"));
llvm::BasicBlock* blockDefault = nullptr;
bool flagFirstPass = true;
for (int variantId = 0; variantId<countVariants; ++variantId){
//Pass information to the late model
flagFirstPass?
Attachments::put<LateBindingT>(guardS, guardVariants.at(variantId))
: Attachments::update<LateBindingT>(guardS, guardVariants.at(variantId));
flagFirstPass = false;
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(
llvm->llvmContext,
"case" + std::to_string(variantId),
function->raw);
if(variantId == 0) blockDefault = blockCase;
builder.SetInsertPoint(blockCase);
auto scopeBody = Decorators<CachedScopeDecoratorTag>::getInterface<>(
function->getScopeUnit(expr.blocks.back()));
scopeBody->reset();
llvm::Value* resultCase = scopeBody->compile();
ret->addIncoming(resultCase, builder.GetInsertBlock());
instructionSwitch->addCase(llvm::dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, variantId)), blockCase);
builder.CreateBr(blockEpilog);
}
instructionSwitch->setDefaultDest(blockDefault);
builder.SetInsertPoint(blockEpilog);
return ret;
}
}}

Event Timeline