versions.h
No OneTemporary

File Metadata

Created
Thu, Jul 9, 8:16 AM

versions.h

/* 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/.
*
* versions.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on January 21, 2017, 1:24 PM
*/
/**
* \file versions.h
* \brief Versions-aware compilation support
*/
#include "pass/versionspass.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
namespace xreate {
class CompilePass;
namespace compilation {
class ICodeScopeUnit;
class IFunctionUnit;
}
namespace versions{
/**\brief Versioned variables code scope level compilation support
*
* Decorates \ref xreate::compilation::ICodeScopeUnit to enable versioned variables compilation.
* An order of variables computation is determined by \ref VersionsPass.
* \extends xreate::compilation::ICodeScopeUnit
* \sa VersionsPass, VersionsGraph
*/
template<class Parent>
class VersionsScopeDecorator: public Parent{
typedef VersionsScopeDecorator<Parent> SELF;
public:
VersionsScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
virtual llvm::Value* processSymbol(const Symbol& s, std::string hintSymbol=""){
if (Attachments::exists<VersionImposedDependency>(s)){
const std::list<Symbol> dependencies = Attachments::get<VersionImposedDependency>(s);
for(const Symbol& symbolDependent: dependencies){
processSymbol(symbolDependent);
}
}
llvm::Value* result = Parent::processSymbol(s, hintSymbol);
if (s.identifier.version == VERSION_INIT){
llvm::Value* storage = SELF::processIntrinsicInit(result->getType(), hintSymbol);
setSymbolStorage(s, storage);
processIntrinsicCopy(result, storage);
return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
} else if (s.identifier.version != VERSION_NONE){
Symbol symbolInitVersion = getSymbolInitVersion(s);
llvm::Value* storage = getSymbolStorage(symbolInitVersion);
processIntrinsicCopy(result, storage);
return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
}
return result;
}
llvm::Value*
processIntrinsicInit(llvm::Type* typeStorage, const std::string& hintVarDecl=""){
LLVMLayer* llvm = compilation::ICodeScopeUnit::pass->man->llvm;
llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm->llvmContext);
llvm::ConstantInt* constOne = llvm::ConstantInt::get(tyInt, 1, false);
return llvm->builder.CreateAlloca(typeStorage, constOne, hintVarDecl);
}
void
processIntrinsicCopy(llvm::Value* value, llvm::Value* storage){
compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateStore(value, storage);
}
private:
std::map<Symbol, llvm::Value*> __symbolStorage;
static Symbol
getSymbolInitVersion(const Symbol& s){
return Symbol{ScopedSymbol{s.identifier.id, VERSION_INIT}, s.scope};
}
llvm::Value*
getSymbolStorage(const Symbol& s){
return __symbolStorage.at(s);
}
void setSymbolStorage(const Symbol& s, llvm::Value* storage){
__symbolStorage[s] = storage;
}
};
/**
* \brief A Versions-aware function level decorator. Not used currently.
*/
template<class Parent>
class VersionedFunctionDecorator : public Parent {
public:
VersionedFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p){}
protected:
std::vector<llvm::Type*> prepareArguments() {
std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
return arguments;
}
};
} } //end of namespace xreate::versions

Event Timeline