调用LLVM Intrinsic函数时LLVMBuildExtractValue触发空指针崩溃求助
问题原因及修复方案
根本原因
错误定义了llvm.sadd.with.overflow.i64的函数返回类型,导致后续LLVMBuildExtractValue操作非法Value对象,触发空指针访问。
llvm.sadd.with.overflow.i64是LLVM提供的带溢出检测的加法内在函数,它的返回类型不是单个i64,而是一个包含两个元素的聚合结构体:
- 索引0:加法运算结果(
i64类型) - 索引1:溢出标志(
i1布尔类型)
你的代码中错误地将函数返回类型设置为LLVMInt64Type(),这会导致LLVMBuildCall生成的v_res不是合法的聚合类型值。当调用LLVMBuildExtractValue尝试提取索引1的元素时,LLVM内部处理非法Value对象时触发空指针访问(对应崩溃栈中llvm::Value::getContext() const访问0x0地址)。
修复代码
修改函数返回类型的定义,创建正确的结构体返回类型:
v_fn = LLVMGetNamedFunction(mod, "llvm.sadd.with.overflow.i64"); if (!v_fn) { LLVMTypeRef param_types[2]; LLVMTypeRef ret_types[2]; LLVMTypeRef v_fn_type; param_types[0] = LLVMInt64Type(); param_types[1] = LLVMInt64Type(); // 定义正确的返回结构体类型:i64(结果)+ i1(溢出标志) ret_types[0] = LLVMInt64Type(); ret_types[1] = LLVMInt1Type(); LLVMTypeRef ret_struct_type = LLVMStructType(ret_types, 2, 0); v_fn_type = LLVMFunctionType(ret_struct_type, param_types, lengthof(param_types), 0); v_fn = LLVMAddFunction(mod, "llvm.sadd.with.overflow.i64", v_fn_type); } params[0] = l_int64_const(1); params[1] = l_int64_const(1); v_res = LLVMBuildCall(b, v_fn, params, lengthof(params), ""); v_flag = LLVMBuildExtractValue(b, v_res, 1, ""); // 注意:溢出标志是i1类型,无需调用LLVMBuildIsNotNull,直接使用即可 // v_flag = LLVMBuildIsNotNull(b, v_flag, "");
额外说明
- 溢出标志本身是
i1布尔类型,LLVMBuildIsNotNull是用于指针类型的判断逻辑,此处属于冗余代码,建议移除。 - 修复函数类型后,
LLVMBuildCall会生成合法的聚合类型值,LLVMBuildExtractValue可正常提取对应索引的元素,不会再触发空指针崩溃。
内容的提问来源于stack exchange,提问作者tutu
相关产品推荐
相关产品推荐

