@@ -39,6 +39,7 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
3939 size_t functionIndex = 0 ;
4040 llvm::Function *currentFunc = beginFunction (functionIndex);
4141 std::vector<IfStatement> ifStatements;
42+ std::vector<Loop> loops;
4243
4344 // Execute recorded steps
4445 for (const Step &step : m_steps) {
@@ -134,6 +135,77 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
134135 ifStatements.pop_back ();
135136 break ;
136137 }
138+
139+ case Step::Type::BeginRepeatLoop: {
140+ Loop loop;
141+ loop.isRepeatLoop = true ;
142+
143+ // index = 0
144+ llvm::Constant *zero = llvm::ConstantInt::get (m_builder.getInt64Ty (), 0 , true );
145+ loop.index = m_builder.CreateAlloca (m_builder.getInt64Ty ());
146+ m_builder.CreateStore (zero, loop.index );
147+
148+ // Create branches
149+ llvm::BasicBlock *roundBranch = llvm::BasicBlock::Create (m_ctx, " " , currentFunc);
150+ loop.conditionBranch = llvm::BasicBlock::Create (m_ctx, " " , currentFunc);
151+ loop.afterLoop = llvm::BasicBlock::Create (m_ctx, " " , currentFunc);
152+
153+ // Convert last reg to double
154+ assert (step.args .size () == 1 );
155+ llvm::Value *count = m_builder.CreateCall (resolve_value_toDouble (), step.args [0 ]->value );
156+
157+ // Clamp count if <= 0 (we can skip the loop if count is not positive)
158+ llvm::Value *comparison = m_builder.CreateFCmpULE (count, llvm::ConstantFP::get (m_ctx, llvm::APFloat (0.0 )));
159+ m_builder.CreateCondBr (comparison, loop.afterLoop , roundBranch);
160+
161+ // Round (Scratch-specific behavior)
162+ m_builder.SetInsertPoint (roundBranch);
163+ llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration (m_module.get (), llvm::Intrinsic::round, { count->getType () });
164+ count = m_builder.CreateCall (roundFunc, { count });
165+ count = m_builder.CreateFPToSI (count, m_builder.getInt64Ty ()); // cast to signed integer
166+
167+ // Jump to condition branch
168+ m_builder.CreateBr (loop.conditionBranch );
169+
170+ // Check index
171+ m_builder.SetInsertPoint (loop.conditionBranch );
172+
173+ llvm::BasicBlock *body = llvm::BasicBlock::Create (m_ctx, " " , currentFunc);
174+
175+ if (!loop.afterLoop )
176+ loop.afterLoop = llvm::BasicBlock::Create (m_ctx, " " , currentFunc);
177+
178+ llvm::Value *currentIndex = m_builder.CreateLoad (m_builder.getInt64Ty (), loop.index );
179+ comparison = m_builder.CreateICmpULT (currentIndex, count);
180+ m_builder.CreateCondBr (comparison, body, loop.afterLoop );
181+
182+ // Switch to body branch
183+ m_builder.SetInsertPoint (body);
184+
185+ loops.push_back (loop);
186+ break ;
187+ }
188+
189+ case Step::Type::EndLoop: {
190+ assert (!loops.empty ());
191+ Loop &loop = loops.back ();
192+
193+ if (loop.isRepeatLoop ) {
194+ // Increment index
195+ llvm::Value *currentIndex = m_builder.CreateLoad (m_builder.getInt64Ty (), loop.index );
196+ llvm::Value *incremented = m_builder.CreateAdd (currentIndex, llvm::ConstantInt::get (m_builder.getInt64Ty (), 1 , true ));
197+ m_builder.CreateStore (incremented, loop.index );
198+ }
199+
200+ // Jump to the condition branch
201+ m_builder.CreateBr (loop.conditionBranch );
202+
203+ // Switch to the branch after the loop
204+ m_builder.SetInsertPoint (loop.afterLoop );
205+
206+ loops.pop_back ();
207+ break ;
208+ }
137209 }
138210 }
139211
@@ -222,10 +294,16 @@ void LLVMCodeBuilder::endIf()
222294
223295void LLVMCodeBuilder::beginRepeatLoop ()
224296{
297+ Step step (Step::Type::BeginRepeatLoop);
298+ assert (!m_tmpRegs.empty ());
299+ step.args .push_back (m_tmpRegs.back ());
300+ m_tmpRegs.pop_back ();
301+ m_steps.push_back (step);
225302}
226303
227304void LLVMCodeBuilder::endLoop ()
228305{
306+ m_steps.push_back (Step (Step::Type::EndLoop));
229307}
230308
231309void LLVMCodeBuilder::yield ()
@@ -360,6 +438,11 @@ llvm::FunctionCallee LLVMCodeBuilder::resolve_value_assign_special()
360438 return resolveFunction (" value_assign_special" , llvm::FunctionType::get (m_builder.getVoidTy (), { m_valueDataType->getPointerTo (), m_builder.getInt32Ty () }, false ));
361439}
362440
441+ llvm::FunctionCallee LLVMCodeBuilder::resolve_value_toDouble ()
442+ {
443+ return resolveFunction (" value_toDouble" , llvm::FunctionType::get (m_builder.getDoubleTy (), m_valueDataType->getPointerTo (), false ));
444+ }
445+
363446llvm::FunctionCallee LLVMCodeBuilder::resolve_value_toBool ()
364447{
365448 return resolveFunction (" value_toBool" , llvm::FunctionType::get (m_builder.getInt1Ty (), m_valueDataType->getPointerTo (), false ));
0 commit comments