You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在libgccjit中正确导入并调用memcpy函数?

在libgccjit中正确导入并调用memcpy的方法

问题背景

我正在用libgccjit构建测试用JIT函数,需要导入memcpy但操作失败。尝试用gcc_jit_context_get_builtin_function导入__builtin_memcpy没成功,两次尝试的代码和报错如下:

第一次尝试代码

void generate_memcpy_code(void){
    gcc_jit_context *ctxt;
    gcc_jit_type *void_ptr_type, *void_type, *int_type;
    gcc_jit_type *param_types[3];
    gcc_jit_param *params[3];
    gcc_jit_function *func;
    gcc_jit_block *block;
    gcc_jit_lvalue *dst_lval, *src_lval;
    gcc_jit_rvalue *size_val;

    ctxt = gcc_jit_context_acquire();

    void_type = gcc_jit_context_get_type( ctxt, GCC_JIT_TYPE_VOID );
    void_ptr_type = gcc_jit_context_get_type( ctxt, GCC_JIT_TYPE_VOID_PTR );
    int_type = gcc_jit_context_get_type( ctxt, GCC_JIT_TYPE_INT );

    param_types[0] = void_ptr_type;
    param_types[1] = void_ptr_type;
    param_types[2] = int_type;

    params[0] = gcc_jit_context_new_param(ctxt, NULL, void_ptr_type, "dst");
    params[1] = gcc_jit_context_new_param(ctxt, NULL, void_ptr_type, "src");
    params[2] = gcc_jit_context_new_param(ctxt, NULL, int_type, "size");

    func = gcc_jit_context_new_function(ctxt, NULL,
        GCC_JIT_FUNCTION_EXPORTED,
        void_type,
        "my_memcpy",
        3, params,
        0 );

    block = gcc_jit_function_new_block(func, "body");

    dst_lval = gcc_jit_param_as_lvalue( gcc_jit_function_get_param(func, 0) );
    src_lval = gcc_jit_param_as_lvalue( gcc_jit_function_get_param(func, 1) );
    size_val = gcc_jit_param_as_rvalue( gcc_jit_function_get_param(func, 2) );

    gcc_jit_rvalue *args[3] = {
        gcc_jit_lvalue_as_rvalue(dst_lval),
        gcc_jit_lvalue_as_rvalue(src_lval),
        size_val
    };

    gcc_jit_rvalue *memcpy_call = gcc_jit_context_new_call(
        ctxt, NULL, gcc_jit_context_get_builtin_function(ctxt, "__builtin_memcpy"),
        3, args);

    gcc_jit_block_add_eval(block, NULL, memcpy_call);
    gcc_jit_context_compile(ctxt);
    gcc_jit_context_release(ctxt);
}

报错信息

libgccjit.so: error: unimplemented primitive type for builtin: 34
libgccjit.so: error: gcc_jit_context_new_call: NULL function
libgccjit.so: error: gcc_jit_block_add_eval: NULL rvalue
libgccjit.so: error: unterminated block in my_memcpy: body

第二次尝试代码(封装导入)

gcc_jit_location *memcpy_loc = gcc_jit_context_new_location( ctxt,
            "/home/yli137/openmpi/reorder_concept/libgcc.h",
            4,
            6 );

    gcc_jit_function *memcpy_function = gcc_jit_context_new_function( ctxt,
            memcpy_loc,
            GCC_JIT_FUNCTION_IMPORTED,
            void_type,
            "generate_memcpy",
            3,
            inputs,
            0 );

    gcc_jit_rvalue *memcpy_call = gcc_jit_context_new_call(
            ctxt, NULL, memcpy_function,
            3, args);

    gcc_jit_block_add_eval(block, memcpy_loc, memcpy_call);

报错信息

libgccjit.so: error: /tmp/libgccjit-1xJjYm/fake.so: undefined symbol: generate_memcpy
gcc_jit_result_get_code: NULL result
Segmentation fault

正确实现方式

修正后的完整代码

#include <libgccjit.h>
#include <stddef.h> // 用于size_t类型定义

void generate_memcpy_code(void){
    gcc_jit_context *ctxt;
    gcc_jit_type *void_ptr_type, *void_type, *size_t_type;
    gcc_jit_param *params[3];
    gcc_jit_function *func, *memcpy_func;
    gcc_jit_block *block;
    gcc_jit_rvalue *args[3];

    ctxt = gcc_jit_context_acquire();

    // 获取基础类型
    void_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_VOID);
    void_ptr_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_VOID_PTR);
    size_t_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_SIZE_T); // 使用标准size类型

    // 创建my_memcpy函数的参数
    params[0] = gcc_jit_context_new_param(ctxt, NULL, void_ptr_type, "dst");
    params[1] = gcc_jit_context_new_param(ctxt, NULL, gcc_jit_type_get_const(void_ptr_type), "src"); // src应为const void*
    params[2] = gcc_jit_context_new_param(ctxt, NULL, size_t_type, "size");

    // 创建导出的my_memcpy函数
    func = gcc_jit_context_new_function(ctxt, NULL,
        GCC_JIT_FUNCTION_EXPORTED,
        void_type,
        "my_memcpy",
        3, params,
        0);

    // 导入标准库的memcpy函数
    gcc_jit_type *memcpy_param_types[3] = {
        void_ptr_type,
        gcc_jit_type_get_const(void_ptr_type),
        size_t_type
    };
    memcpy_func = gcc_jit_context_new_function(ctxt, NULL,
        GCC_JIT_FUNCTION_IMPORTED,
        void_ptr_type, // memcpy返回值为void*
        "memcpy",
        3, memcpy_param_types,
        0);

    block = gcc_jit_function_new_block(func, "body");

    // 准备调用memcpy的参数
    args[0] = gcc_jit_param_as_rvalue(params[0]);
    args[1] = gcc_jit_param_as_rvalue(params[1]);
    args[2] = gcc_jit_param_as_rvalue(params[2]);

    // 调用memcpy
    gcc_jit_rvalue *memcpy_call = gcc_jit_context_new_call(ctxt, NULL, memcpy_func, 3, args);
    gcc_jit_block_add_eval(block, NULL, memcpy_call);

    // 终止代码块:添加void返回语句
    gcc_jit_block_end_with_void_return(block, NULL);

    // 编译并释放上下文
    gcc_jit_context_compile(ctxt);
    gcc_jit_context_release(ctxt);
}

关键修正点说明

  • 匹配标准memcpy签名:memcpy的标准签名是void* memcpy(void* dest, const void* src, size_t n),需将第二个参数改为const void*,第三个参数使用size_t而非int,这是之前类型错误的核心原因。
  • 导入正确的函数:直接导入系统标准库的memcpy,而非自定义的generate_memcpy,避免未定义符号错误。
  • 终止代码块:所有函数块必须以返回或跳转语句结束,添加gcc_jit_block_end_with_void_return解决"unterminated block"报错。
  • 避免使用__builtin_memcpy:libgccjit对部分内置函数的支持有限,直接调用会触发类型不兼容问题,优先导入标准库函数。

内容的提问来源于stack exchange,提问作者WhoAmIWhereAmIWhatIAmDoing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 09:25:21