transformations.cpp
No OneTemporary

File Metadata

Created
Fri, Mar 13, 2:46 AM

transformations.cpp

/*
* File: Transformations.cpp
* Author: pgess
*
* Created on June 18, 2016, 6:23 PM
*/
#include "compilation/transformations.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
#include <llvm/IR/Value.h>
using namespace llvm;
namespace xreate { namespace compilation {
Transformations::Transformations(CompilePass* passCompilation): pass(passCompilation) {
}
void
Transformations::subscribe(const std::string& annotation, int handler){
__subscriptions.emplace(annotation, handler);
}
bool
Transformations::isAcceptable(const Expression& expression){
//check subscription based on expression attachments
if (Attachments::get<Expression, Transformations>(expression, {false, 0}).flagSubscribed){
return true;
}
//subscription based on expression annotations;
if (expression.tags.size() == 0) return false;
for (auto tag: expression.tags) {
if (__subscriptions.count(tag.first)){
return true;
}
}
return false;
}
Expression
Transformations::transform(const Expression& expression, const Context& ctx){
Expression result = expression;
for (auto handler: getAppropriateTransformers(expression)){
result = handler->transform(result, ctx);
}
return result;
}
llvm::Value*
Transformations::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
for (auto handler: getAppropriateTransformers(expression)){
raw = handler->transform(expression, raw, ctx);
}
return raw;
}
std::list<Transformer*>
Transformations::getAppropriateTransformers(const Expression& expression){
std::list<Transformer*> result;
for (auto tag: expression.tags) {
if (__subscriptions.count(tag.first)){
auto handlers = __subscriptions.equal_range(tag.first);
for (auto handlerIt=handlers.first; handlerIt!= handlers.second; ++handlerIt){
Transformer* handler = __transformers[handlerIt->second];
if (handler->isAcceptable(expression)){
result.push_back(handler);
}
}
}
}
auto subscriberInternal = Attachments::get<Expression, Transformations>(expression, {false, 0});
if (subscriberInternal.flagSubscribed){
result.push_back(__transformers[subscriberInternal.subscriberId]);
}
return result;
}
TransformerSaturation::TransformerSaturation(Transformations* man)
: __man(man) {
man->subscribe("break", TransformerInfo<TransformerSaturation>::id);
}
bool
TransformerSaturation::isAcceptable(const Expression& expression){
return true;
}
bool
TransformerSaturation::exists() const{
return __block != nullptr;
}
llvm::Value*
TransformerSaturation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){
__block = __man->pass->man->llvm->builder.GetInsertBlock();
return raw;
}
llvm::BasicBlock*
TransformerSaturation::getBlock() const{
return __block;
}
void
TransformerSaturation::inject(llvm::BasicBlock* blockAllocation, llvm::BasicBlock* blockExit, compilation::Context context){
llvm::Type* tyInt1 = llvm::Type::getInt1Ty(llvm::getGlobalContext());
llvm::Value* valueConstOne = llvm::ConstantInt::get(tyInt1, 1);
llvm::Value* valueConstFalse = llvm::ConstantInt::get(tyInt1, 0);
//allocation of saturation flag
IRBuilder<> builderAlloca(blockAllocation, blockAllocation->getFirstInsertionPt());
llvm::Value* flagSaturation = builderAlloca.CreateAlloca(tyInt1, valueConstOne, "flagSaturation");
builderAlloca.CreateStore(valueConstFalse, flagSaturation, true);
//set up saturation flag
llvm::BasicBlock* blockSaturation = __block;
IRBuilder<> builderSaturation(blockSaturation, blockSaturation->getFirstInsertionPt());
builderSaturation.CreateStore(valueConstOne, flagSaturation, true);
//check saturation flag:
//TODO remove blockContinue, receive from caller block to continue.
llvm::BasicBlock *blockContinue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "continue", context.function->raw);
context.pass->man->llvm->builder.CreateCondBr(context.pass->man->llvm->builder.CreateLoad(flagSaturation), blockExit, blockContinue);
context.pass->man->llvm->builder.SetInsertPoint(blockContinue);
}
}}

Event Timeline