在遵循 LLVM Kaleidoscope 教程并使用 LLVM-C API 复制它时,我遇到了以下断言失败:
断言失败:New->getType() == getType() && "replaceAllUses of value with new value of different type!",文件 C:\llvm-project\llvm\lib\IR\Value.cpp,第 494 行
我已经看到在两种情况下产生了这个错误:
- CFGSimplificationPass 被添加到 pass 管理器中,并且 LLVMRunFunctionPassManager 函数在一个像这样分支的函数上被调用(下面的完整示例):
br i1 true, label %then, label %else
- 未添加 CFGSimplificationPass;LLVMRunFunctionPassManager 成功。但是,运行 LLVMRunFunction 时会产生相同的错误。
以下生成的代码很好:
%cmptmp = fcmp ult double %x, 3.000000e+00
br i1 %cmptmp, label %then, label %else
我为第一个实例创建了一个小型复制器:
#include "llvm-c\Core.h"
#include "llvm-c\Transforms\Utils.h"
#include "llvm-c\Transforms\Scalar.h"
#include "llvm-c\Analysis.h"
LLVMContextRef context;
LLVMModuleRef module;
LLVMBuilderRef builder;
LLVMPassManagerRef passManager;
void initializePassManager() {
passManager = LLVMCreateFunctionPassManagerForModule(module);
LLVMAddPromoteMemoryToRegisterPass(passManager);
LLVMAddInstructionCombiningPass(passManager);
LLVMAddReassociatePass(passManager);
LLVMAddGVNPass(passManager);
LLVMAddCFGSimplificationPass(passManager);
}
LLVMValueRef codegenProto() {
LLVMTypeRef parameters[1];
LLVMTypeRef functionType = LLVMFunctionType
(LLVMDoubleTypeInContext(context),
parameters,
0,
0);
LLVMValueRef func = LLVMAddFunction(module, "__anon_expr", functionType);
LLVMSetLinkage(func, LLVMExternalLinkage);
return func;
}
LLVMValueRef codegenBody() {
LLVMValueRef x = LLVMConstReal(LLVMDoubleTypeInContext(context), 1.0);
LLVMValueRef y = LLVMConstReal(LLVMDoubleTypeInContext(context), 2.0);
LLVMValueRef conditionValue = LLVMBuildFCmp(builder, LLVMRealULT, x, y, "cmptmp");
LLVMBasicBlockRef currentBasicBlock = LLVMGetInsertBlock(builder);
LLVMValueRef func = LLVMGetBasicBlockParent(currentBasicBlock);
LLVMBasicBlockRef thenBasicBlock = LLVMAppendBasicBlockInContext(context, func, "then");
LLVMBasicBlockRef elseBasicBlock = LLVMCreateBasicBlockInContext(context, "else");
LLVMBasicBlockRef mergeBasicBlock = LLVMCreateBasicBlockInContext(context, "ifcont");
LLVMValueRef condBr = LLVMBuildCondBr(builder, conditionValue, thenBasicBlock, elseBasicBlock);
LLVMPositionBuilderAtEnd(builder, thenBasicBlock);
LLVMValueRef thenValue = LLVMConstReal(LLVMDoubleTypeInContext(context), 37.0);
LLVMBuildBr(builder, mergeBasicBlock);
thenBasicBlock = LLVMGetInsertBlock(builder);
LLVMAppendExistingBasicBlock(func, elseBasicBlock);
LLVMPositionBuilderAtEnd(builder, elseBasicBlock);
LLVMValueRef elseValue = LLVMConstReal(LLVMDoubleTypeInContext(context), 42.0);
LLVMBuildBr(builder, mergeBasicBlock);
elseBasicBlock = LLVMGetInsertBlock(builder);
LLVMAppendExistingBasicBlock(func, mergeBasicBlock);
LLVMPositionBuilderAtEnd(builder, mergeBasicBlock);
LLVMValueRef phiNode = LLVMBuildPhi(builder, LLVMDoubleTypeInContext(context), "iftmp");
LLVMValueRef values[2] = {thenValue, elseValue};
LLVMBasicBlockRef blocks[2] = {thenBasicBlock, elseBasicBlock};
LLVMAddIncoming(phiNode, values, blocks, 2);
return phiNode;
}
LLVMValueRef codegenFunc() {
LLVMValueRef proto = codegenProto();
LLVMBasicBlockRef basicBlock = LLVMAppendBasicBlock(proto, "entry");
LLVMPositionBuilderAtEnd(builder, basicBlock);
LLVMValueRef body = codegenBody();
LLVMBuildRet(builder, body);
LLVMDumpModule(module);
LLVMVerifyFunction(proto, LLVMPrintMessageAction);
LLVMRunFunctionPassManager(passManager,proto);
return proto;
}
int main() {
LLVMLinkInMCJIT();
LLVMInitializeX86Target();
LLVMInitializeX86TargetMC();
LLVMInitializeX86TargetInfo();
LLVMInitializeX86AsmPrinter();
LLVMInitializeX86AsmParser();
context = LLVMContextCreate();
module = LLVMModuleCreateWithNameInContext("JIT", context);
builder = LLVMCreateBuilderInContext(context);
initializePassManager();
LLVMValueRef IR = codegenFunc();
LLVMDisposeBuilder(builder);
LLVMDisposeModule(module);
LLVMContextDispose(context);
LLVMDisposePassManager(passManager);
return 0;
}
LLVMDumpModule 函数为我提供以下输出:
; ModuleID = 'JIT'
source_filename = "JIT"
define double @__anon_expr() {
entry:
br i1 true, label %then, label %else
then: ; preds = %entry
br label %ifcont
else: ; preds = %entry
br label %ifcont
ifcont: ; preds = %else, %then
%iftmp = phi double [ 3.700000e+01, %then ], [ 4.200000e+01, %else ]
ret double %iftmp
}
我已经看到 LLVM Kaleidoscope 示例项目生成的相同代码,运行没有问题。我的 MCJIT 设置是否存在固有问题,或者我是否遇到了 LLVM 错误?