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 ); } }