pub unsafe fn gen_extend(
        &mut self,
        builder: LLVMBuilderRef,
        intrinsics: &mut Intrinsics,
        run: LLVMValueRef,
        vector: LLVMValueRef,
        size: LLVMValueRef,
    ) -> WeldResult<LLVMValueRef> {
        use self::llvm_sys::LLVMIntPredicate::LLVMIntSGT;
        if self.extend.is_none() {
            trace!("Generated extend");
            let mut arg_tys = [self.vector_ty, self.i64_type(), self.run_handle_type()];
            let ret_ty = self.vector_ty;

            let name = format!("{}.extend", self.name);
            let (function, builder, entry_block) = self.define_function(ret_ty, &mut arg_tys, name);

            let realloc_block = LLVMAppendBasicBlockInContext(self.context, function, c_str!(""));
            let finish_block = LLVMAppendBasicBlockInContext(self.context, function, c_str!(""));

            let vector = LLVMGetParam(function, 0);
            let requested_size = LLVMGetParam(function, 1);
            let run_handle = LLVMGetParam(function, 2);

            let current_size = LLVMBuildExtractValue(builder, vector, SIZE_INDEX, c_str!(""));

            let resize_flag = LLVMBuildICmp(
                builder,
                LLVMIntSGT,
                requested_size,
                current_size,
                c_str!(""),
            );
            LLVMBuildCondBr(builder, resize_flag, realloc_block, finish_block);
            trace!("finished entry block");

            // Build block where memory is grown to accomdate the requested size.
            LLVMPositionBuilderAtEnd(builder, realloc_block);
            let pointer = LLVMBuildExtractValue(builder, vector, POINTER_INDEX, c_str!(""));
            let alloc_size = LLVMBuildNSWMul(
                builder,
                requested_size,
                self.size_of(self.elem_ty),
                c_str!(""),
            );
            let raw_pointer = LLVMBuildBitCast(
                builder,
                pointer,
                LLVMPointerType(self.i8_type(), 0),
                c_str!(""),
            );
            let bytes = intrinsics.call_weld_run_realloc(
                builder,
                run_handle,
                raw_pointer,
                alloc_size,
                Some(c_str!("")),
            );
            let resized_elements =
                LLVMBuildBitCast(builder, bytes, LLVMTypeOf(pointer), c_str!(""));

            let resized = LLVMBuildInsertValue(
                builder,
                LLVMGetUndef(self.vector_ty),
                resized_elements,
                POINTER_INDEX,
                c_str!(""),
            );
            let resized =
                LLVMBuildInsertValue(builder, resized, requested_size, SIZE_INDEX, c_str!(""));
            LLVMBuildBr(builder, finish_block);
            trace!("finished reallocation block");

            LLVMPositionBuilderAtEnd(builder, finish_block);
            let return_value = LLVMBuildPhi(builder, self.vector_ty, c_str!(""));
            let mut values = [vector, resized];
            let mut blocks = [entry_block, realloc_block];
            LLVMAddIncoming(
                return_value,
                values.as_mut_ptr(),
                blocks.as_mut_ptr(),
                values.len() as u32,
            );
            LLVMBuildRet(builder, return_value);
            trace!("finished extend");

            self.extend = Some(function);
            LLVMDisposeBuilder(builder);
        }

        let mut args = [vector, size, run];
        Ok(LLVMBuildCall(
            builder,
            self.extend.unwrap(),
            args.as_mut_ptr(),
            args.len() as u32,
            c_str!(""),
        ))
    }
Generates the `extend` method on vectors and calls it.

This method grows the capacity of vector to exactly `size` and returns a new vector. If
the input vector can already accomodate `size` elements, the same vector is returned
unmodified.

This method modifies the size to be the new capacity if the vector is resized.
weld/src/codegen/llvm2/vector.rs