unsafe fn gen_for_internal(
        &mut self,
        ctx: &mut FunctionContext<'_>,
        output: &Symbol,
        parfor: &ParallelForData,
    ) -> WeldResult<()> {
        let iterations = self.gen_bounds_check(ctx, parfor)?;

        let sir_function = &ctx.sir_program.funcs[parfor.body];
        assert!(sir_function.loop_body);

        self.gen_loop_body_function(ctx.sir_program, sir_function, parfor)?;
        let body_function = self.functions[&parfor.body];

        // The parameters of the body function have symbol names that must exist in the current
        // context.
        let mut arguments = vec![];
        for (symbol, _) in sir_function.params.iter() {
            let value = self.load(ctx.builder, ctx.get_value(symbol)?)?;
            arguments.push(value);
        }
        // The body function has an additional arguement representing the number of iterations.
        arguments.push(iterations);
        // Last argument is always the run handle.
        arguments.push(ctx.get_run());

        // Call the body function, which runs the loop and updates the builder. The updated builder
        // is returned to the current function.
        let builder = LLVMBuildCall(
            ctx.builder,
            body_function,
            arguments.as_mut_ptr(),
            arguments.len() as u32,
            c_str!(""),
        );
        LLVMSetInstructionCallConv(builder, SIR_FUNC_CALL_CONV);
        // XXX what is parfor.builder now...
        LLVMBuildStore(ctx.builder, builder, ctx.get_value(&parfor.builder)?);
        LLVMBuildStore(ctx.builder, builder, ctx.get_value(&output)?);

        Ok(())
    }
Entry point to generating a for loop.
weld/src/codegen/llvm2/builder/for_loop.rs