Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3995697
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
Tue, Jul 7, 9:35 PM
Size
9 KB
Mime Type
text/x-c++
Expires
Thu, Jul 9, 9:35 PM (1 d, 10 h)
Engine
blob
Format
Raw Data
Handle
271714
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 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);
}
default: break;
}
assert(false);
return nullptr;
}
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){
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);
}
return aggrRaw;
}
llvm::Value*
FlyIR::create(llvm::Value* sourceRaw, CodeScope* body, const std::string& hintAlias){
RecordIR recordIR(__context);
compilation::LambdaIR lambdaIR(__context.pass);
llvm::Function* fnTransform = lambdaIR.compile(body, hintAlias);
llvm::Value* resultRaw = recordIR.init({
sourceRaw->getType(),
fnTransform->getFunctionType()->getPointerTo()
});
resultRaw = __context.pass->man->llvm->irBuilder.CreateInsertValue(
resultRaw, sourceRaw, 0);
resultRaw = __context.pass->man->llvm->irBuilder.CreateInsertValue(
resultRaw, fnTransform, 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* elTRaw = llvm->toLLVMType(ExpandedType(aggrT->__operands.at(0)));
llvm::Type* resultTRaw = types.getPreferredIntTy();
llvm::Type* fnTnsfTRaw = llvm::FunctionType::get(resultTRaw, llvm::ArrayRef<llvm::Type*>(elTRaw), false);
std::vector<llvm::Type*> fieldsVec = {
sourceTRaw,
fnTnsfTRaw->getPointerTo()
};
llvm::ArrayRef<llvm::Type *> fieldsArr(fieldsVec);
llvm::StructType* resultTR = llvm::StructType::get(llvm->llvmContext, fieldsArr, false);
return resultTR;
}
llvm::Value*
FlyIR::getTransformFn(llvm::Value* aggrRaw){
LLVMLayer* llvm = __context.pass->man->llvm;
llvm::Value* fnRaw = llvm->irBuilder.CreateExtractValue(aggrRaw, llvm::ArrayRef<unsigned>{1});
return fnRaw;
}
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* loopS = expr.blocks.front();
return create(sourceRaw, loopS, 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);
}
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() {
std::unique_ptr<IFwdIteratorIR> itSrcIR(IFwdIteratorIR::createByHint(__hint.hintSrc, __aggrT, __context));
return itSrcIR->begin();
}
llvm::Value*
FwdIteratorIR<ON_THE_FLY>::end() {
std::unique_ptr<IFwdIteratorIR> itSrcIR(IFwdIteratorIR::createByHint(__hint.hintSrc, __aggrT, __context));
return itSrcIR->end();
}
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 compilerFly(__hint, __context);
llvm::Value* aggrSrcRaw = compilerFly.getSourceAggr(aggrRaw);
llvm::Value* valueSrcRaw = srcIterIR->get(aggrSrcRaw, idxRaw);
FlyIR flyIR(__hint, __context);
llvm::Value* fnTnsfRaw = flyIR.getTransformFn(aggrRaw);
llvm::Type* fnTnsfTRawRaw = llvm::cast<llvm::PointerType>(fnTnsfRaw->getType())->getElementType();
llvm::FunctionType* fnTnsfTRaw = llvm::cast<llvm::FunctionType>(fnTnsfTRawRaw);
compilation::BruteFnInvocation fnTnsfInvoc(fnTnsfRaw, fnTnsfTRaw, __context.pass->man->llvm);
return fnTnsfInvoc({valueSrcRaw}, hintAlias);
}
}} //end of xreate::containers
Event Timeline
Log In to Comment