CG::ExprValue CreateValueCache::buildExprValue( CG::BasicBlockBuilder &basicBlockBuilder, CG::Usage usage, std::string const &lValueErrorDesc ) const { if ( usage == CG::USAGE_LVALUE ) throw Exception( "cannot be used as l-values" ); RC::Handle<CG::Context> context = basicBlockBuilder.getContext(); llvm::LLVMContext &llvmContext = context->getLLVMContext(); CG::ExprType inputExprType = m_input->getExprType( basicBlockBuilder ); if ( !RT::isValueProducer( inputExprType.getAdapter()->getType() ) ) throw CG::Error( getLocation(), "input must be a value producer" ); RC::ConstHandle<CG::ValueProducerAdapter> valueProducerAdapter = RC::ConstHandle<CG::ValueProducerAdapter>::StaticCast( inputExprType.getAdapter() ); RC::ConstHandle<CG::Adapter> valueAdapter = valueProducerAdapter->getValueAdapter(); CG::ExprValue inputExprRValue = m_input->buildExprValue( basicBlockBuilder, CG::USAGE_RVALUE, lValueErrorDesc ); llvm::Value *resultLValue = valueProducerAdapter->llvmAlloca( basicBlockBuilder, "result" ); valueProducerAdapter->llvmInit( basicBlockBuilder, resultLValue ); basicBlockBuilder.getScope().put( CG::VariableSymbol::Create( CG::ExprValue( valueProducerAdapter, CG::USAGE_LVALUE, context, resultLValue ) ) ); std::vector<llvm::Type const *> argTypes; argTypes.push_back( valueProducerAdapter->llvmLType( context ) ); argTypes.push_back( valueProducerAdapter->llvmLType( context ) ); llvm::FunctionType const *funcType = llvm::FunctionType::get( llvm::Type::getVoidTy( llvmContext ), argTypes, false ); llvm::Constant *func = basicBlockBuilder.getModuleBuilder()->getOrInsertFunction( "__MR_CreateValueCache", funcType ); basicBlockBuilder->CreateCall2( func, inputExprRValue.getValue(), resultLValue ); return CG::ExprValue( valueProducerAdapter, CG::USAGE_RVALUE, context, valueProducerAdapter->llvmLValueToRValue( basicBlockBuilder, resultLValue ) ); }
CG::ExprType IndexOp::getExprType( CG::BasicBlockBuilder &basicBlockBuilder ) const { CG::ExprType exprType = m_expr->getExprType( basicBlockBuilder ); exprType.getAdapter()->llvmCompileToModule( basicBlockBuilder.getModuleBuilder() ); if ( RT::isArray( exprType.getAdapter()->getType() ) ) { RC::ConstHandle<CG::ArrayAdapter> arrayType = RC::ConstHandle<CG::ArrayAdapter>::StaticCast( exprType.getAdapter() ); RC::ConstHandle<CG::Adapter> memberAdapter = arrayType->getMemberAdapter(); memberAdapter->llvmCompileToModule( basicBlockBuilder.getModuleBuilder() ); return CG::ExprType( memberAdapter, exprType.getUsage() ); } else if ( RT::isDict( exprType.getAdapter()->getType() ) ) { RC::ConstHandle<CG::DictAdapter> dictType = RC::ConstHandle<CG::DictAdapter>::StaticCast( exprType.getAdapter() ); RC::ConstHandle<CG::Adapter> valueAdapter = dictType->getValueAdapter(); valueAdapter->llvmCompileToModule( basicBlockBuilder.getModuleBuilder() ); return CG::ExprType( valueAdapter, exprType.getUsage() ); } else throw Exception( "only arrays and dictionaries can be indexed" ); }
CG::ExprValue CreateArrayGenerator::buildExprValue( CG::BasicBlockBuilder &basicBlockBuilder, CG::Usage usage, std::string const &lValueErrorDesc ) const { if ( usage == CG::USAGE_LVALUE ) throw Exception( "cannot be used as l-values" ); RC::Handle<CG::Context> context = basicBlockBuilder.getContext(); llvm::LLVMContext &llvmContext = context->getLLVMContext(); RC::ConstHandle<CG::SizeAdapter> sizeAdapter = basicBlockBuilder.getManager()->getSizeAdapter(); RC::ConstHandle<CG::Symbol> operatorSymbol = basicBlockBuilder.getScope().get( m_operatorName ); if ( !operatorSymbol ) throw CG::Error( getLocation(), _(m_operatorName) + ": operator not found" ); if ( !operatorSymbol->isPencil() ) throw CG::Error( getLocation(), _(m_operatorName) + ": not an operator" ); RC::ConstHandle<CG::PencilSymbol> pencil = RC::ConstHandle<CG::PencilSymbol>::StaticCast( operatorSymbol ); CG::Function const *function = pencil->getUniqueFunction( getLocation(), "operator " + _(m_operatorName) ); std::vector<CG::FunctionParam> const &operatorParams = function->getParams(); if ( operatorParams.size() < 1 ) throw MR::ArrayGeneratorOperator::GetPrototypeException(); CG::ExprType countExprType = m_count->getExprType( basicBlockBuilder ); if ( !RT::isValueProducer( countExprType.getAdapter()->getType() ) ) throw CG::Error( getLocation(), "count must be a value producer" ); RC::ConstHandle<CG::ValueProducerAdapter> countValueProducerAdapter = RC::ConstHandle<CG::ValueProducerAdapter>::StaticCast( countExprType.getAdapter() ); RC::ConstHandle<CG::Adapter> countAdapter = countValueProducerAdapter->getValueAdapter(); if ( countAdapter != sizeAdapter ) throw CG::Error( getLocation(), "count value type must be 'Size'" ); CG::ExprValue countValueProducerExprValue = m_count->buildExprValue( basicBlockBuilder, CG::USAGE_RVALUE, lValueErrorDesc ); if ( operatorParams[0].getUsage() != CG::USAGE_LVALUE ) throw CG::Error( getLocation(), "operator value parameter must be an 'io' parameter" ); RC::ConstHandle<CG::Adapter> outputAdapter = operatorParams[0].getAdapter(); RC::ConstHandle<CG::ArrayProducerAdapter> outputArrayProducerAdapter = basicBlockBuilder.getManager()->getArrayProducerOf( outputAdapter ); llvm::Value *resultLValue = outputArrayProducerAdapter->llvmAlloca( basicBlockBuilder, "result" ); outputArrayProducerAdapter->llvmInit( basicBlockBuilder, resultLValue ); basicBlockBuilder.getScope().put( CG::VariableSymbol::Create( CG::ExprValue( outputArrayProducerAdapter, CG::USAGE_LVALUE, context, resultLValue ) ) ); bool needCall = true; if ( operatorParams.size() >= 2 ) { if ( operatorParams[1].getAdapter() != sizeAdapter ) throw CG::Error( getLocation(), "operator index parameter type (" + operatorParams[1].getAdapter()->getUserName() + ") must be 'Size'" ); if ( operatorParams[1].getUsage() != CG::USAGE_RVALUE ) throw CG::Error( getLocation(), "operator index parameter must be an 'in' parameter" ); if ( operatorParams.size() >= 3 ) { if ( operatorParams[2].getAdapter() != sizeAdapter ) throw CG::Error( getLocation(), "operator index parameter type (" + operatorParams[2].getAdapter()->getUserName() + ") must be 'Size'" ); if ( operatorParams[2].getUsage() != CG::USAGE_RVALUE ) throw CG::Error( getLocation(), "operator index parameter must be an 'in' parameter" ); if ( operatorParams.size() >= 4 ) { if ( operatorParams.size() > 4 ) throw MR::ArrayGeneratorOperator::GetPrototypeException(); if ( !m_shared ) throw CG::Error( getLocation(), "operator takes a shared value but no shared value is provided" ); CG::ExprType sharedExprType = m_shared->getExprType( basicBlockBuilder ); if ( !RT::isValueProducer( sharedExprType.getAdapter()->getType() ) ) throw CG::Error( getLocation(), "shared value must be a value producer" ); RC::ConstHandle<CG::ValueProducerAdapter> sharedValueProducerAdapter = RC::ConstHandle<CG::ValueProducerAdapter>::StaticCast( sharedExprType.getAdapter() ); RC::ConstHandle<CG::Adapter> sharedAdapter = sharedValueProducerAdapter->getValueAdapter(); if ( operatorParams[3].getAdapter() != sharedAdapter ) throw CG::Error( getLocation(), "operator shared value parameter type (" + operatorParams[3].getAdapter()->getUserName() + ") does not match shared value type (" + sharedAdapter->getUserName() + ")" ); if ( operatorParams[3].getUsage() != CG::USAGE_RVALUE ) throw CG::Error( getLocation(), "operator shared value parameter must be an 'in' parameter" ); CG::ExprValue sharedExprRValue = m_shared->buildExprValue( basicBlockBuilder, CG::USAGE_RVALUE, lValueErrorDesc ); std::vector<llvm::Type const *> argTypes; argTypes.push_back( llvm::Type::getInt8PtrTy( llvmContext ) ); // function argTypes.push_back( sizeAdapter->llvmRType( context ) ); // numParams argTypes.push_back( countValueProducerAdapter->llvmLType( context ) ); // count value producer argTypes.push_back( sharedValueProducerAdapter->llvmLType( context ) ); // shared value producer argTypes.push_back( llvm::Type::getInt8PtrTy( llvmContext ) ); // output array producer adapter argTypes.push_back( outputArrayProducerAdapter->llvmLType( context ) ); // output array producer llvm::FunctionType const *funcType = llvm::FunctionType::get( llvm::Type::getVoidTy( llvmContext ), argTypes, false ); llvm::Constant *func = basicBlockBuilder.getModuleBuilder()->getOrInsertFunction( "__MR_CreateArrayGenerator_4", funcType ); std::vector<llvm::Value *> args; args.push_back( basicBlockBuilder->CreateBitCast( function->getLLVMFunction(), llvm::Type::getInt8PtrTy( llvmContext ) ) ); args.push_back( sizeAdapter->llvmConst( context, operatorParams.size() ) ); args.push_back( countValueProducerExprValue.getValue() ); args.push_back( sharedExprRValue.getValue() ); args.push_back( outputArrayProducerAdapter->llvmAdapterPtr( basicBlockBuilder ) ); args.push_back( resultLValue ); basicBlockBuilder->CreateCall( func, args.begin(), args.end() ); needCall = false; } } } if ( needCall ) { std::vector<llvm::Type const *> argTypes; argTypes.push_back( llvm::Type::getInt8PtrTy( llvmContext ) ); // function argTypes.push_back( sizeAdapter->llvmRType( context ) ); // numParams argTypes.push_back( countValueProducerAdapter->llvmLType( context ) ); // count value producer argTypes.push_back( llvm::Type::getInt8PtrTy( llvmContext ) ); // output array producer adapter argTypes.push_back( outputArrayProducerAdapter->llvmLType( context ) ); // output array producer llvm::FunctionType const *funcType = llvm::FunctionType::get( llvm::Type::getVoidTy( llvmContext ), argTypes, false ); llvm::Constant *func = basicBlockBuilder.getModuleBuilder()->getOrInsertFunction( "__MR_CreateArrayGenerator_3", funcType ); std::vector<llvm::Value *> args; args.push_back( basicBlockBuilder->CreateBitCast( function->getLLVMFunction(), llvm::Type::getInt8PtrTy( llvmContext ) ) ); args.push_back( sizeAdapter->llvmConst( context, operatorParams.size() ) ); args.push_back( countValueProducerExprValue.getValue() ); args.push_back( outputArrayProducerAdapter->llvmAdapterPtr( basicBlockBuilder ) ); args.push_back( resultLValue ); basicBlockBuilder->CreateCall( func, args.begin(), args.end() ); } return CG::ExprValue( outputArrayProducerAdapter, CG::USAGE_RVALUE, context, outputArrayProducerAdapter->llvmLValueToRValue( basicBlockBuilder, resultLValue ) ); }
CG::ExprValue IndexOp::buildExprValue( CG::BasicBlockBuilder &basicBlockBuilder, CG::Usage usage, std::string const &lValueErrorDesc ) const { CG::ExprValue result( basicBlockBuilder.getContext() ); try { CG::ExprValue arrayExprValue = m_expr->buildExprValue( basicBlockBuilder, usage, lValueErrorDesc ); RC::ConstHandle<CG::Adapter> adapter = arrayExprValue.getAdapter(); if ( RT::isArray( arrayExprValue.getAdapter()->getType() ) ) { RC::ConstHandle<CG::ArrayAdapter> arrayAdapter = RC::ConstHandle<CG::ArrayAdapter>::StaticCast( adapter ); CG::ExprValue indexExprValue = m_indexExpr->buildExprValue( basicBlockBuilder, CG::USAGE_RVALUE, lValueErrorDesc ); RC::ConstHandle< CG::SizeAdapter > sizeAdapter = basicBlockBuilder.getManager()->getSizeAdapter(); llvm::Value *indexExprRValue = sizeAdapter->llvmCast( basicBlockBuilder, indexExprValue ); if ( indexExprRValue ) { switch ( usage ) { case CG::USAGE_LVALUE: result = CG::ExprValue( arrayAdapter->getMemberAdapter(), CG::USAGE_LVALUE, basicBlockBuilder.getContext(), arrayAdapter->llvmNonConstIndexOp( basicBlockBuilder, arrayExprValue.getValue(), indexExprRValue, &getLocation() ) ); break; default: result = CG::ExprValue( arrayAdapter->getMemberAdapter(), CG::USAGE_RVALUE, basicBlockBuilder.getContext(), arrayAdapter->llvmConstIndexOp( basicBlockBuilder, arrayExprValue.getValue(), indexExprRValue, &getLocation() ) ); break; } } } else if ( RT::isDict( arrayExprValue.getAdapter()->getType() ) ) { RC::ConstHandle<CG::DictAdapter> dictAdapter = RC::ConstHandle<CG::DictAdapter>::StaticCast( adapter ); CG::ExprValue indexExprValue = m_indexExpr->buildExprValue( basicBlockBuilder, CG::USAGE_RVALUE, lValueErrorDesc ); RC::ConstHandle<CG::ComparableAdapter> keyAdapter = dictAdapter->getKeyAdapter(); llvm::Value *indexExprRValue = keyAdapter->llvmCast( basicBlockBuilder, indexExprValue ); if ( indexExprRValue ) { switch ( usage ) { case CG::USAGE_LVALUE: result = CG::ExprValue( dictAdapter->getValueAdapter(), CG::USAGE_LVALUE, basicBlockBuilder.getContext(), dictAdapter->llvmGetLValue( basicBlockBuilder, arrayExprValue.getValue(), indexExprRValue ) ); break; default: result = CG::ExprValue( dictAdapter->getValueAdapter(), CG::USAGE_RVALUE, basicBlockBuilder.getContext(), dictAdapter->llvmGetRValue( basicBlockBuilder, arrayExprValue.getValue(), indexExprRValue ) ); break; } } } else throw CG::Error( getLocation(), "only arrays and dictionaries can be indexed" ); } catch ( CG::Error e ) { throw e; } catch ( Exception e ) { throw CG::Error( getLocation(), e ); } return result; }
void ContainerLoop::llvmCompileToBuilder( CG::BasicBlockBuilder &parentBasicBlockBuilder, CG::Diagnostics &diagnostics ) const { try { CG::BasicBlockBuilder &basicBlockBuilder = parentBasicBlockBuilder; RC::Handle<CG::Context> context = parentBasicBlockBuilder.getContext(); CG::ExprValue dictExprValue = m_dictExpr->buildExprValue( parentBasicBlockBuilder, CG::USAGE_UNSPECIFIED, "" ); RC::ConstHandle<CG::Adapter> adapter = dictExprValue.getAdapter(); if ( !RT::isDict( adapter->getType() ) ) throw CG::Error( m_dictExpr->getLocation(), "must be a dictionary" ); RC::ConstHandle<CG::DictAdapter> dictAdapter = RC::ConstHandle<CG::DictAdapter>::StaticCast( adapter ); RC::ConstHandle<CG::ComparableAdapter> keyAdapter = dictAdapter->getKeyAdapter(); RC::ConstHandle<CG::Adapter> valueAdapter = dictAdapter->getValueAdapter(); llvm::Type *nodePtrType = dictAdapter->getLLVMNodePtrType( context ); llvm::Instruction *nodePtrPtr = new llvm::AllocaInst( nodePtrType ); nodePtrPtr->setName( m_keyName ); // [pzion 20111019] We allocate variables at the top of the function CG::FunctionBuilder &functionBuilder = parentBasicBlockBuilder.getFunctionBuilder(); llvm::BasicBlock &entryBB = functionBuilder->getEntryBlock(); llvm::BasicBlock::iterator it = entryBB.begin(); while ( it != entryBB.end() ) { if ( !llvm::isa<llvm::AllocaInst>(*it) ) break; ++it; } entryBB.getInstList().insert( it, nodePtrPtr ); llvm::Value *bitsPtr = basicBlockBuilder->CreateLoad( dictExprValue.getValue() ); llvm::BasicBlock *startBB = parentBasicBlockBuilder.getFunctionBuilder().createBasicBlock( "containerLoopStart" ); llvm::BasicBlock *checkBB = parentBasicBlockBuilder.getFunctionBuilder().createBasicBlock( "containerLoopCheck" ); llvm::BasicBlock *bodyBB = parentBasicBlockBuilder.getFunctionBuilder().createBasicBlock( "containerLoopBody" ); llvm::BasicBlock *stepBB = parentBasicBlockBuilder.getFunctionBuilder().createBasicBlock( "containerLoopStep" ); llvm::BasicBlock *endBB = parentBasicBlockBuilder.getFunctionBuilder().createBasicBlock( "containerLoopEnd" ); basicBlockBuilder->CreateCondBr( basicBlockBuilder->CreateIsNotNull( bitsPtr ), startBB, endBB ); // [pzion 20111019] Load bits->firstNode into llvmNodePtrPtr basicBlockBuilder->SetInsertPoint( startBB ); llvm::Value *firstNodePtrPtr = basicBlockBuilder->CreateStructGEP( bitsPtr, 3 ); llvm::Value *firstNodePtr = basicBlockBuilder->CreateLoad( firstNodePtrPtr ); basicBlockBuilder->CreateStore( firstNodePtr, nodePtrPtr ); basicBlockBuilder->CreateBr( checkBB ); basicBlockBuilder->SetInsertPoint( checkBB ); llvm::Value *nodePtr = basicBlockBuilder->CreateLoad( nodePtrPtr ); basicBlockBuilder->CreateCondBr( basicBlockBuilder->CreateIsNull( nodePtr ), endBB, bodyBB ); basicBlockBuilder->SetInsertPoint( bodyBB ); llvm::Value *bitsNextNodePtrPtr = basicBlockBuilder->CreateStructGEP( nodePtr, 1 ); llvm::Value *bitsNextNodePtr = basicBlockBuilder->CreatePointerCast( basicBlockBuilder->CreateLoad( bitsNextNodePtrPtr ), nodePtrType ); { CG::LoopScope loopScope( parentBasicBlockBuilder.getScope(), endBB, stepBB ); llvm::Value *keyLValue = basicBlockBuilder->CreatePointerCast( basicBlockBuilder->CreateStructGEP( nodePtr, 5 ), keyAdapter->llvmLType( context ) ); llvm::Value *keyRValue = keyAdapter->llvmLValueToRValue( basicBlockBuilder, keyLValue ); loopScope.put( m_keyName, CG::ParameterSymbol::Create( CG::ExprValue( keyAdapter, CG::USAGE_RVALUE, context, keyRValue ) ) ); llvm::Value *valueRValue = 0; if ( m_valueName.length() > 0 ) { llvm::Value *valueLValue = basicBlockBuilder->CreatePointerCast( basicBlockBuilder->CreateConstGEP2_32( basicBlockBuilder->CreateStructGEP( nodePtr, 5 ), 0, keyAdapter->getImpl()->getAllocSize() ), valueAdapter->llvmLType( context ) ); switch ( dictExprValue.getUsage() ) { case CG::USAGE_RVALUE: { valueRValue = valueAdapter->llvmLValueToRValue( basicBlockBuilder, valueLValue ); loopScope.put( m_valueName, CG::ParameterSymbol::Create( CG::ExprValue( valueAdapter, CG::USAGE_RVALUE, context, valueRValue ) ) ); } break; case CG::USAGE_LVALUE: { loopScope.put( m_valueName, CG::ParameterSymbol::Create( CG::ExprValue( valueAdapter, CG::USAGE_LVALUE, context, valueLValue ) ) ); } break; default: FABRIC_ASSERT(false); break; } } CG::BasicBlockBuilder loopBasicBlockBuilder( parentBasicBlockBuilder, loopScope ); m_body->llvmCompileToBuilder( loopBasicBlockBuilder, diagnostics ); loopScope.llvmUnwind( loopBasicBlockBuilder ); } basicBlockBuilder->CreateBr( stepBB ); basicBlockBuilder->SetInsertPoint( stepBB ); basicBlockBuilder->CreateStore( bitsNextNodePtr, nodePtrPtr ); basicBlockBuilder->CreateBr( checkBB ); basicBlockBuilder->SetInsertPoint( endBB ); } catch ( CG::Error e ) { addError( diagnostics, e ); } catch ( Exception e ) { addError( diagnostics, e ); } }