void ReturnStatement::llvmCompileToBuilder( CG::BasicBlockBuilder &basicBlockBuilder, CG::Diagnostics &diagnostics ) const { try { CG::ReturnInfo const &returnInfo = basicBlockBuilder.getFunctionBuilder().getScope().getReturnInfo(); if ( basicBlockBuilder->GetInsertBlock()->getTerminator() ) throw CG::Error( getLocation(), "unreachable code" ); CG::ExprValue returnExprValue( CG::ExprValue( basicBlockBuilder.getContext() ) ); if ( m_expr ) { if ( !returnInfo ) throw CG::Error( getLocation(), "functions with no return types do not return values" ); returnExprValue = m_expr->buildExprValue( basicBlockBuilder, CG::USAGE_RVALUE, "cannot be assigned to" ); } else { if ( returnInfo ) throw CG::Error( getLocation(), "function must return a value" ); } basicBlockBuilder.getScope().llvmReturn( basicBlockBuilder, returnExprValue ); } catch ( Exception e ) { addError( diagnostics, e ); } }
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 ); } }