Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F4819137
containers.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
Sun, Aug 23, 11:52 PM
Size
12 KB
Mime Type
text/x-c++
Expires
Tue, Aug 25, 11:52 PM (11 h, 26 m)
Engine
blob
Format
Raw Data
Handle
286638
Attached To
rXR Xreate
containers.cpp
View Options
/* 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/.
*
* File: containers.cpp
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file compilation/containers.h
* \brief Containers compilation support. See [Containers](/d/concepts/containers/) in the Xreate's documentation.
*/
#include "compilation/containers.h"
#include "compilation/targetinterpretation.h"
#include "aux/expressions.h"
#include "compilation/containers/arrays.h"
#include "compilation/lambdas.h"
#include "analysis/predefinedanns.h"
#include "analysis/utils.h"
using namespace xreate::compilation;
using namespace std;
namespace xreate { namespace containers{
ImplementationType
IContainersIR::getImplementation(const Expression& aggrE, AST* ast){
auto manPredefined = analysis::PredefinedAnns::instance();
const Expression& hintE = analysis::findAnnByType(aggrE, ExpandedType(manPredefined.hintsContT), ast);
assert(hintE.isValid());
return (ImplementationType ) hintE.getValueDouble();
}
IContainersIR *
IContainersIR::create(const Expression &aggrE, const TypeAnnotation &expectedT, const compilation::Context &context){
ExpandedType aggrT = context.pass->man->root->getType(aggrE, expectedT);
Expression aggr2E;
if (aggrE.__state == Expression::IDENT && !aggrE.tags.size()){
Symbol aggrS = Attachments::get<IdentifierSymbol>(aggrE);
aggr2E = CodeScope::getDefinition(aggrS);
} else {
aggr2E = aggrE;
}
switch(aggr2E.op){
case Operator::LIST:{
typehints::ArrayHint aggrHint = typehints::find(
aggr2E, typehints::ArrayHint{aggr2E.operands.size()}
);
return new ArrayIR(aggrT, aggrHint, context);
}
default:
typehints::ArrayHint aggrHint = typehints::find(
aggr2E, typehints::ArrayHint{0}
);
assert(aggrHint.size != 0);
return new ArrayIR(aggrT, aggrHint, context);
}
assert(false);
return nullptr;
}
llvm::Type*
IContainersIR::getRawType(const Expression& aggrE, const ExpandedType& aggrT, LLVMLayer* llvm){
auto manPredefined = analysis::PredefinedAnns::instance();
const Expression& hintE = analysis::findAnnByType(aggrE, ExpandedType(manPredefined.hintsContT), llvm->ast);
assert(hintE.isValid());
return getRawTypeByHint(hintE, aggrT, llvm);
}
llvm::Type*
IContainersIR::getRawTypeByHint(const Expression& hintE, const ExpandedType& aggrT, LLVMLayer* llvm) {
ImplementationType hintImpl = (ImplementationType ) hintE.getValueDouble();
switch (hintImpl){
case SOLID: {
typehints::ArrayHint hint = typehints::parse<typehints::ArrayHint>(hintE);
return ArrayIR::getRawType(aggrT, hint, llvm);
}
case ON_THE_FLY:{
typehints::FlyHint hint = typehints::parse<typehints::FlyHint>(hintE);
return FlyIR::getRawType(aggrT, hint, llvm);
}
case RANGE: {
return RangeIR::getRawType(aggrT, llvm);
}
}
assert(false);
return nullptr;
}
uint64_t
IContainersIR::getAllocSize(const Expression& aggrE, LLVMLayer* llvm){
switch( getImplementation(aggrE, llvm->ast)){
case ON_THE_FLY: {
return FlyIR::getAllocSize(aggrE, llvm);
}
case SOLID:{
typehints::ArrayHint hint = typehints::find<typehints::ArrayHint>(aggrE, {});
return ArrayIR::getAllocSize(llvm->ast->getType(aggrE), hint, llvm);
}
default: break;
}
return 0;
}
llvm::Value *
RecordIR::init(llvm::StructType *tyAggr){
return llvm::UndefValue::get(tyAggr);
}
llvm::Value*
RecordIR::init(std::forward_list<llvm::Type*> fields){
std::vector<llvm::Type*> fieldsVec(fields.begin(), fields.end());
llvm::ArrayRef<llvm::Type *> fieldsArr(fieldsVec);
llvm::StructType* resultTR = llvm::StructType::get(__context.pass->man->llvm->llvmContext, fieldsArr, false);
return init(resultTR);
}
llvm::Value *
RecordIR::update(llvm::Value *aggrRaw, const ExpandedType &aggrT, const Expression &updE, const std::string& hintAlias){
interpretation::InterpretationScope *scopeI12n =
__context.pass->targetInterpretation->transformContext(__context);
TypesHelper helper(__context.pass->man->llvm);
const auto &fields = helper.getRecordFields(aggrT);
std::map<std::string, size_t> indexFields;
for(size_t i = 0, size = fields.size(); i < size; ++i){
indexFields.emplace(fields[i], i);
}
for(const auto &entry: reprListAsDict(updE)){
unsigned keyId;
std::string keyHint;
const Expression keyE = scopeI12n->process(entry.first);
switch(keyE.__state){
case Expression::STRING:
keyId = indexFields.at(keyE.getValueString());
keyHint = keyE.getValueString();
break;
case Expression::NUMBER:
keyId = keyE.getValueDouble();
keyHint = aggrT->fields.at(keyId);
break;
default:
assert(false);
break;
}
const TypeAnnotation &valueT = aggrT->__operands.at(keyId);
llvm::Value *valueRaw = __context.scope->process(entry.second, keyHint, valueT);
aggrRaw = __context.pass->man->llvm->irBuilder.CreateInsertValue(
aggrRaw,
valueRaw,
keyId);
}
aggrRaw->setName(hintAlias);
return aggrRaw;
}
uint64_t
FlyIR::getAllocSize(const Expression& expr, LLVMLayer* llvm){
assert(expr.op == Operator::MAP);
return LambdaIR::getAllocSize(expr.blocks.front(), llvm);
}
llvm::Value*
FlyIR::init(llvm::Value* sourceRaw, CodeScope* body, Allocator* allocator, const std::string& hintAlias){
RecordIR recordIR(__context);
compilation::LambdaIR lambdaIR(__context);
llvm::Value* lambdaTransform = lambdaIR.compile(body, allocator, hintAlias);
llvm::Value* resultRaw = recordIR.init({
sourceRaw->getType(),
lambdaTransform->getType()
});
resultRaw = __context.pass->man->llvm->irBuilder.CreateInsertValue(
resultRaw, sourceRaw, 0);
resultRaw = __context.pass->man->llvm->irBuilder.CreateInsertValue(
resultRaw, lambdaTransform, 1);
return resultRaw;
}
llvm::Type*
FlyIR::getRawType(const ExpandedType& aggrT, const typehints::FlyHint& hint, LLVMLayer* llvm){
assert(aggrT->__operator == TypeOperator::ARRAY);
TypesHelper types(llvm);
llvm::Type* sourceTRaw = IContainersIR::getRawTypeByHint(hint.hintSrc, aggrT, llvm);
llvm::Type* elRawT = llvm->toLLVMType(ExpandedType(aggrT->__operands.at(0)));
//ERROR: !!LOST INFO ON ARG TYPE !
llvm::Type* lmbdTnsfRawT = LambdaIR::getRawType(elRawT, {elRawT}, llvm);
std::vector<llvm::Type*> fieldsVec = {
sourceTRaw,
lmbdTnsfRawT
};
llvm::ArrayRef<llvm::Type *> fieldsArr(fieldsVec);
llvm::StructType* resultTR = llvm::StructType::get(llvm->llvmContext, fieldsArr, false);
return resultTR;
}
llvm::Value*
FlyIR::getTransformLambda(llvm::Value* aggrRaw){
LLVMLayer* llvm = __context.pass->man->llvm;
llvm::Value* lambdaRaw = llvm->irBuilder.CreateExtractValue(aggrRaw, llvm::ArrayRef<unsigned>{1});
return lambdaRaw;
}
llvm::Value*
FlyIR::getSourceAggr(llvm::Value* aggrRaw){
LLVMLayer* llvm = __context.pass->man->llvm;
return llvm->irBuilder.CreateExtractValue(aggrRaw, llvm::ArrayRef<unsigned>{0});
}
llvm::Value*
FlyIR::operatorMap(const Expression& expr, const std::string& hintAlias){
const Expression& sourceE = expr.getOperands().at(0);
llvm::Value* sourceRaw = __context.scope->process(sourceE);
CodeScope* loopSc = expr.blocks.front();
std::unique_ptr<Allocator> allocator(Allocator::create(expr, __context));
return init(sourceRaw, loopSc, allocator.get(), hintAlias);
}
FlyIR::FlyIR(typehints::FlyHint hint, compilation::Context context)
: __hint(hint), __context(context){}
IFwdIteratorIR*
IFwdIteratorIR::createByHint(const Expression& hintE, const ExpandedType& aggrT, const compilation::Context& context){
ImplementationType hintType = (ImplementationType) hintE.getValueDouble();
switch(hintType){
case SOLID:{
ArrayIR compiler(aggrT, typehints::parse<typehints::ArrayHint>(hintE), context);
return new FwdIteratorIR<SOLID>(compiler);
}
case ON_THE_FLY:{
return new FwdIteratorIR<ON_THE_FLY>(typehints::parse<typehints::FlyHint>(hintE), aggrT, context);
}
case RANGE: {
return new FwdIteratorIR<RANGE>(context);
}
default: break;
}
assert(false);
return nullptr;
}
IFwdIteratorIR*
IFwdIteratorIR::create(const Expression& aggrE, const ExpandedType& aggrT, const compilation::Context& context){
auto manPredefined = analysis::PredefinedAnns::instance();
const Expression& hintE = analysis::findAnnByType(
aggrE,
ExpandedType(manPredefined.hintsContT),
context.pass->man->root
);
assert(hintE.isValid());
return createByHint(hintE, aggrT, context);
}
llvm::Value*
FwdIteratorIR<ON_THE_FLY>::begin(llvm::Value* aggrRaw) {
std::unique_ptr<IFwdIteratorIR> itSrcIR(IFwdIteratorIR::createByHint(__hint.hintSrc, __aggrT, __context));
FlyIR compilerFly(__hint, __context);
llvm::Value* aggrSrcRaw = compilerFly.getSourceAggr(aggrRaw);
return itSrcIR->begin(aggrSrcRaw);
}
llvm::Value*
FwdIteratorIR<ON_THE_FLY>::end(llvm::Value* aggrRaw) {
std::unique_ptr<IFwdIteratorIR> itSrcIR(IFwdIteratorIR::createByHint(__hint.hintSrc, __aggrT, __context));
FlyIR compilerFly(__hint, __context);
llvm::Value* aggrSrcRaw = compilerFly.getSourceAggr(aggrRaw);
return itSrcIR->end(aggrSrcRaw);
}
llvm::Value*
FwdIteratorIR<ON_THE_FLY>::advance(llvm::Value* idxRaw, const std::string& hintAlias){
std::unique_ptr<IFwdIteratorIR> itSrcIR(IFwdIteratorIR::createByHint(__hint.hintSrc, __aggrT, __context));
return itSrcIR->advance(idxRaw, hintAlias);
}
llvm::Value*
FwdIteratorIR<ON_THE_FLY>::get(llvm::Value* aggrRaw, llvm::Value *idxRaw, const std::string &hintAlias){
std::unique_ptr<IFwdIteratorIR> srcIterIR(IFwdIteratorIR::createByHint(__hint.hintSrc, __aggrT, __context));
FlyIR flyIR(__hint, __context);
compilation::LambdaIR lambdaIR(__context);
llvm::Value* aggrSrcRaw = flyIR.getSourceAggr(aggrRaw);
llvm::Value* valueSrcRaw = srcIterIR->get(aggrSrcRaw, idxRaw);
llvm::Value* lambdaTnsfRaw = flyIR.getTransformLambda(aggrRaw);
std::unique_ptr<compilation::IFnInvocation> fnTnsfInvoc(lambdaIR.getFnInvocation(lambdaTnsfRaw));
return (*fnTnsfInvoc)({valueSrcRaw}, hintAlias);
}
llvm::Value*
RangeIR::create(const ExpandedType& aggrT, llvm::Value* valueFromRaw, llvm::Value* valueToRaw){
RecordIR recordIR(__context);
LLVMLayer* llvm = __context.pass->man->llvm;
llvm::Value* aggrRaw = recordIR.init(getRawType(aggrT, llvm));
aggrRaw = llvm->irBuilder.CreateInsertValue(aggrRaw, valueFromRaw, 0);
aggrRaw = llvm->irBuilder.CreateInsertValue(aggrRaw, valueToRaw, 1);
return aggrRaw;
}
llvm::Value*
RangeIR::init(const Expression& aggrE, const ExpandedType& aggrT, const std::string& hintAlias){
assert(aggrE.op == Operator::LIST_RANGE);
assert(aggrE.operands.size()==2);
llvm::Value* valueFromRaw = __context.scope->process(aggrE.operands.at(0));
llvm::Value* valueToRaw = __context.scope->process(aggrE.operands.at(1));
return create(aggrT, valueFromRaw, valueToRaw);
}
llvm::Value*
RangeIR::getValueFrom(llvm::Value* aggrRaw){
LLVMLayer* llvm = __context.pass->man->llvm;
return llvm->irBuilder.CreateExtractValue(aggrRaw, llvm::ArrayRef<unsigned>{0});
}
llvm::Value*
RangeIR::getValueTo(llvm::Value* aggrRaw){
LLVMLayer* llvm = __context.pass->man->llvm;
return llvm->irBuilder.CreateExtractValue(aggrRaw, llvm::ArrayRef<unsigned>{1});
}
llvm::StructType*
RangeIR::getRawType(const ExpandedType& aggrT, LLVMLayer* llvm){
assert(aggrT->__operator == TypeOperator::ARRAY);
ExpandedType elT(aggrT->__operands.at(0));
llvm::Type* elRawT = llvm->toLLVMType(elT);
std::vector<llvm::Type*> fieldsVec = {elRawT, elRawT};
llvm::ArrayRef<llvm::Type *> fieldsArr(fieldsVec);
llvm::StructType* rangeRawT = llvm::StructType::get(llvm->llvmContext, fieldsArr, false);
return rangeRawT;
}
llvm::Value*
FwdIteratorIR<RANGE>::begin(llvm::Value* aggrRaw){
RangeIR compiler(__context);
return compiler.getValueFrom(aggrRaw);
}
llvm::Value*
FwdIteratorIR<RANGE>::end(llvm::Value* aggrRaw){
RangeIR compiler(__context);
return compiler.getValueTo(aggrRaw);
}
llvm::Value*
FwdIteratorIR<RANGE>::get(llvm::Value* aggrRaw, llvm::Value *idxRaw, const std::string &hintAlias){
return idxRaw;
}
llvm::Value*
FwdIteratorIR<RANGE>::advance(llvm::Value* idxRaw, const std::string& hintAlias) {
LLVMLayer* llvm = __context.pass->man->llvm;
TypesHelper types(llvm);
llvm::Type* intT = types.getPreferredIntTy();
return llvm->irBuilder.CreateAdd(idxRaw, llvm::ConstantInt::get(intT, 1), hintAlias);
}
}} //end of xreate::containers
Event Timeline
Log In to Comment