@@ -98,9 +98,12 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
9898 // Create list pointers
9999 for (auto &[list, listPtr] : m_listPtrs) {
100100 listPtr.ptr = getListPtr (targetLists, list);
101+
101102 listPtr.dataPtr = m_builder.CreateAlloca (m_valueDataType->getPointerTo ());
102103 m_builder.CreateStore (m_builder.CreateCall (resolve_list_data (), listPtr.ptr ), listPtr.dataPtr );
104+
103105 listPtr.sizePtr = m_builder.CreateCall (resolve_list_size_ptr (), listPtr.ptr );
106+ listPtr.allocatedSizePtr = m_builder.CreateCall (resolve_list_alloc_size_ptr (), listPtr.ptr );
104107 }
105108
106109 // Execute recorded steps
@@ -502,9 +505,32 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
502505 const auto &arg = step.args [0 ];
503506 Compiler::StaticType type = optimizeRegisterType (arg.second );
504507 const LLVMListPtr &listPtr = m_listPtrs[step.workList ];
505- llvm::Value *itemPtr = m_builder.CreateCall (resolve_list_append_empty (), listPtr.ptr );
508+
509+ // Check if enough space is allocated
510+ llvm::Value *allocatedSize = m_builder.CreateLoad (m_builder.getInt64Ty (), listPtr.allocatedSizePtr );
511+ llvm::Value *size = m_builder.CreateLoad (m_builder.getInt64Ty (), listPtr.sizePtr );
512+ llvm::Value *isAllocated = m_builder.CreateICmpUGT (allocatedSize, size);
513+ llvm::BasicBlock *ifBlock = llvm::BasicBlock::Create (m_ctx, " " , func);
514+ llvm::BasicBlock *elseBlock = llvm::BasicBlock::Create (m_ctx, " " , func);
515+ llvm::BasicBlock *nextBlock = llvm::BasicBlock::Create (m_ctx, " " , func);
516+ m_builder.CreateCondBr (isAllocated, ifBlock, elseBlock);
517+
518+ // If there's enough space, use the allocated memory
519+ m_builder.SetInsertPoint (ifBlock);
520+ llvm::Value *itemPtr = getListItem (m_builder.CreateLoad (m_valueDataType->getPointerTo (), listPtr.dataPtr ), size);
521+ createInitialValueStore (arg.second , itemPtr, type);
522+ m_builder.CreateStore (m_builder.CreateAdd (size, m_builder.getInt64 (1 )), listPtr.sizePtr );
523+ m_builder.CreateBr (nextBlock);
524+
525+ // Otherwise call appendEmpty()
526+ m_builder.SetInsertPoint (elseBlock);
527+ itemPtr = m_builder.CreateCall (resolve_list_append_empty (), listPtr.ptr );
506528 createInitialValueStore (arg.second , itemPtr, type);
529+ // TODO: Update list data only when needed
507530 m_builder.CreateStore (m_builder.CreateCall (resolve_list_data (), listPtr.ptr ), listPtr.dataPtr );
531+ m_builder.CreateBr (nextBlock);
532+
533+ m_builder.SetInsertPoint (nextBlock);
508534 // TODO: Implement list type prediction
509535 break ;
510536 }
@@ -2058,6 +2084,12 @@ llvm::FunctionCallee LLVMCodeBuilder::resolve_list_size_ptr()
20582084 return resolveFunction (" list_size_ptr" , llvm::FunctionType::get (m_builder.getInt64Ty ()->getPointerTo ()->getPointerTo (), { listPtr }, false ));
20592085}
20602086
2087+ llvm::FunctionCallee LLVMCodeBuilder::resolve_list_alloc_size_ptr ()
2088+ {
2089+ llvm::Type *listPtr = llvm::PointerType::get (llvm::Type::getInt8Ty (m_ctx), 0 );
2090+ return resolveFunction (" list_alloc_size_ptr" , llvm::FunctionType::get (m_builder.getInt64Ty ()->getPointerTo ()->getPointerTo (), { listPtr }, false ));
2091+ }
2092+
20612093llvm::FunctionCallee LLVMCodeBuilder::resolve_strcasecmp ()
20622094{
20632095 llvm::Type *pointerType = llvm::PointerType::get (llvm::Type::getInt8Ty (m_ctx), 0 );
0 commit comments