containers.cpp
No OneTemporary

File Metadata

Created
Sun, Aug 23, 11:52 PM

containers.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/.
*
* 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