unsafe fn declare_sir_function(&mut self, func: &SirFunction) -> WeldResult<()> {
        let mut arg_tys = self.argument_types(func)?;
        arg_tys.push(self.run_handle_type());
        let ret_ty = self.llvm_type(&func.return_type)?;
        let func_ty = LLVMFunctionType(ret_ty, arg_tys.as_mut_ptr(), arg_tys.len() as u32, 0);
        let name = CString::new(format!("f{}", func.id)).unwrap();
        let function = LLVMAddFunction(self.module, name.as_ptr(), func_ty);

        // Add attributes, set linkage, etc.
        llvm_exts::LLVMExtAddDefaultAttrs(self.context(), function);
        LLVMSetLinkage(function, LLVMLinkage::LLVMPrivateLinkage);
        LLVMSetFunctionCallConv(function, SIR_FUNC_CALL_CONV);

        self.functions.insert(func.id, function);
        Ok(())
    }
Declare a function in the SIR module and track its reference.

In addition to the SIR-defined parameters, the runtime adds an `i8*` pointer as the last
argument to each function, representing the handle to the run data. This handle is always
guaranteed to be the last argument.

This method only defines functions and does not generate code for the function.
weld/src/codegen/llvm2/mod.rs