LLVM IRBuilder - 创建 Phi 节点时出现内存错误
LLVM IRBuilder - Memory Error when creating Phi Node
我正在关注 Kaleidoscope tutorial 使用 if-else 表达式制作我自己的语言。我想创建函数根据条件分支到的 2 个块 if
和 else
。然后两个块都分支回 merge
块,我有一个 phi 节点从正确的块获取值。但是,我在调用函数PHINode::addIncoming
时总是出现奇怪的错误,我是不是用错了函数?还是我遗漏了什么?
我创建了一个相当小的例子:
using namespace llvm;
static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<IRBuilder<>> Builder;
static std::unique_ptr<llvm::Module> TheModule;
void InitializeModule() {
// Open a new context and module.
TheContext = std::make_unique<LLVMContext>();
TheModule = std::make_unique<Module>("my prg", *TheContext);
// Create a new builder for the module.
Builder = std::make_unique<IRBuilder<>>(*TheContext);
// Create a main function
std::vector<Type*> Ints(1,
Type::getInt64Ty(*TheContext));
FunctionType* FT =
FunctionType::get(Type::getInt64Ty(*TheContext), Ints, false);
Function* F =
Function::Create(FT, Function::ExternalLinkage, "main", TheModule.get());
BasicBlock* FuncEntry = BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(FuncEntry);
}
int main() {
InitializeModule();
Function* TheFunction = Builder->GetInsertBlock()->getParent();
Value* Zero = ConstantInt::get(*TheContext, APInt(64, 0, true));
Value* One = ConstantInt::get(*TheContext, APInt(64, 1, true));
BasicBlock* ThenBB = BasicBlock::Create(*TheContext, "then");
BasicBlock* ElseBB = BasicBlock::Create(*TheContext, "else");
BasicBlock* MergeBB = BasicBlock::Create(*TheContext, "ifcont");
//branch
Value* Cond = Builder->CreateICmpNE(One, Zero, "ifcond");
Builder->CreateCondBr(Cond, ThenBB, ElseBB);
//then block
TheFunction->getBasicBlockList().push_back(ThenBB);
Builder->SetInsertPoint(ThenBB);
Builder->CreateBr(MergeBB);
ThenBB = Builder->GetInsertBlock();
//else block
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder->SetInsertPoint(ElseBB);
Builder->CreateBr(MergeBB);
ElseBB = Builder->GetInsertBlock();
//merge
TheFunction->getBasicBlockList().push_back(MergeBB);
Builder->SetInsertPoint(MergeBB);
PHINode* PN =
Builder->CreatePHI(Type::getInt64Ty(*TheContext), 2, "iftmp");
PN->addIncoming(Zero, ThenBB);
PN->addIncoming(One, ElseBB);
//Finish function
Builder->CreateRet(PN);
verifyFunction(*TheFunction);
return 0;
}
我正在使用 llvm 的发布版本并使用 Visual Studio 2022 进行编译,这会产生以下运行时错误:
Exception thrown at 0x00007FF7E9774274 in test.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
运行 AddressSanitizer 我得到:
==21908==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x121d66820318 at pc 0x7ff7bd234188 bp 0x00165dd2f840 sp 0x00165dd2f848
READ of size 8 at 0x121d66820318 thread T0
==21908==WARNING: Failed to use and restart external symbolizer!
#0 0x7ff7bd234187 in llvm::Use::set C:\llvm\llvm-project-main\llvm\include\llvm\IR\Value.h:869
#1 0x7ff7bd235599 in llvm::PHINode::addIncoming C:\llvm\llvm-project-main\llvm\include\llvm\IR\Instructions.h:2803
#2 0x7ff7bd2377c8 in main C:\Users\USERNAME\source\repos\test\test.cpp:81
#3 0x7ff7bd31292b in __scrt_common_main_seh d:\a01\_work\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#4 0x7ff91a0d7033 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017033)
#5 0x7ff91ac62650 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180052650)
0x121d66820318 is located 8 bytes to the right of 80-byte region [0x121d668202c0,0x121d66820310)
allocated by thread T0 here:
#0 0x7ff7bd31205a in operator new D:\a01\_work\s\src\vctools\crt\asan\llvm\compiler-rt\lib\asan\asan_win_new_scalar_thunk.cpp:41
#1 0x7ff7bd2374b2 in main C:\Users\USERNAME\source\repos\test\test.cpp:57
#2 0x7ff7bd31292b in __scrt_common_main_seh d:\a01\_work\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#3 0x7ff91a0d7033 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017033)
#4 0x7ff91ac62650 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180052650)
SUMMARY: AddressSanitizer: heap-buffer-overflow C:\llvm\llvm-project-main\llvm\include\llvm\IR\Value.h:869 in llvm::Use::set
Shadow bytes around the buggy address:
0x045313504010: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x045313504020: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa 00 00
0x045313504030: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00
0x045313504040: 00 00 00 00 00 00 fa fa fa fa 00 00 00 00 00 00
0x045313504050: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
=>0x045313504060: 00 00 fa[fa]fa fa 00 00 00 00 00 00 00 00 00 00
0x045313504070: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 fa fa
0x045313504080: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x045313504090: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fd fd
0x0453135040a0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
0x0453135040b0: fd fd fd fd fd fa fa fa fa fa fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==21908==ABORTING
因此,visual studio 中的项目设置不正确。我建议阅读 this 文章,了解如何使用 llvm 正确设置 visual studio。然后,我查看了万花筒教程的官方 vs 项目并复制了设置和属性(不仅仅是包含路径...)。
我正在关注 Kaleidoscope tutorial 使用 if-else 表达式制作我自己的语言。我想创建函数根据条件分支到的 2 个块 if
和 else
。然后两个块都分支回 merge
块,我有一个 phi 节点从正确的块获取值。但是,我在调用函数PHINode::addIncoming
时总是出现奇怪的错误,我是不是用错了函数?还是我遗漏了什么?
我创建了一个相当小的例子:
using namespace llvm;
static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<IRBuilder<>> Builder;
static std::unique_ptr<llvm::Module> TheModule;
void InitializeModule() {
// Open a new context and module.
TheContext = std::make_unique<LLVMContext>();
TheModule = std::make_unique<Module>("my prg", *TheContext);
// Create a new builder for the module.
Builder = std::make_unique<IRBuilder<>>(*TheContext);
// Create a main function
std::vector<Type*> Ints(1,
Type::getInt64Ty(*TheContext));
FunctionType* FT =
FunctionType::get(Type::getInt64Ty(*TheContext), Ints, false);
Function* F =
Function::Create(FT, Function::ExternalLinkage, "main", TheModule.get());
BasicBlock* FuncEntry = BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(FuncEntry);
}
int main() {
InitializeModule();
Function* TheFunction = Builder->GetInsertBlock()->getParent();
Value* Zero = ConstantInt::get(*TheContext, APInt(64, 0, true));
Value* One = ConstantInt::get(*TheContext, APInt(64, 1, true));
BasicBlock* ThenBB = BasicBlock::Create(*TheContext, "then");
BasicBlock* ElseBB = BasicBlock::Create(*TheContext, "else");
BasicBlock* MergeBB = BasicBlock::Create(*TheContext, "ifcont");
//branch
Value* Cond = Builder->CreateICmpNE(One, Zero, "ifcond");
Builder->CreateCondBr(Cond, ThenBB, ElseBB);
//then block
TheFunction->getBasicBlockList().push_back(ThenBB);
Builder->SetInsertPoint(ThenBB);
Builder->CreateBr(MergeBB);
ThenBB = Builder->GetInsertBlock();
//else block
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder->SetInsertPoint(ElseBB);
Builder->CreateBr(MergeBB);
ElseBB = Builder->GetInsertBlock();
//merge
TheFunction->getBasicBlockList().push_back(MergeBB);
Builder->SetInsertPoint(MergeBB);
PHINode* PN =
Builder->CreatePHI(Type::getInt64Ty(*TheContext), 2, "iftmp");
PN->addIncoming(Zero, ThenBB);
PN->addIncoming(One, ElseBB);
//Finish function
Builder->CreateRet(PN);
verifyFunction(*TheFunction);
return 0;
}
我正在使用 llvm 的发布版本并使用 Visual Studio 2022 进行编译,这会产生以下运行时错误:
Exception thrown at 0x00007FF7E9774274 in test.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
运行 AddressSanitizer 我得到:
==21908==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x121d66820318 at pc 0x7ff7bd234188 bp 0x00165dd2f840 sp 0x00165dd2f848
READ of size 8 at 0x121d66820318 thread T0
==21908==WARNING: Failed to use and restart external symbolizer!
#0 0x7ff7bd234187 in llvm::Use::set C:\llvm\llvm-project-main\llvm\include\llvm\IR\Value.h:869
#1 0x7ff7bd235599 in llvm::PHINode::addIncoming C:\llvm\llvm-project-main\llvm\include\llvm\IR\Instructions.h:2803
#2 0x7ff7bd2377c8 in main C:\Users\USERNAME\source\repos\test\test.cpp:81
#3 0x7ff7bd31292b in __scrt_common_main_seh d:\a01\_work\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#4 0x7ff91a0d7033 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017033)
#5 0x7ff91ac62650 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180052650)
0x121d66820318 is located 8 bytes to the right of 80-byte region [0x121d668202c0,0x121d66820310)
allocated by thread T0 here:
#0 0x7ff7bd31205a in operator new D:\a01\_work\s\src\vctools\crt\asan\llvm\compiler-rt\lib\asan\asan_win_new_scalar_thunk.cpp:41
#1 0x7ff7bd2374b2 in main C:\Users\USERNAME\source\repos\test\test.cpp:57
#2 0x7ff7bd31292b in __scrt_common_main_seh d:\a01\_work\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#3 0x7ff91a0d7033 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017033)
#4 0x7ff91ac62650 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180052650)
SUMMARY: AddressSanitizer: heap-buffer-overflow C:\llvm\llvm-project-main\llvm\include\llvm\IR\Value.h:869 in llvm::Use::set
Shadow bytes around the buggy address:
0x045313504010: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x045313504020: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa 00 00
0x045313504030: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00
0x045313504040: 00 00 00 00 00 00 fa fa fa fa 00 00 00 00 00 00
0x045313504050: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
=>0x045313504060: 00 00 fa[fa]fa fa 00 00 00 00 00 00 00 00 00 00
0x045313504070: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 fa fa
0x045313504080: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x045313504090: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fd fd
0x0453135040a0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
0x0453135040b0: fd fd fd fd fd fa fa fa fa fa fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==21908==ABORTING
因此,visual studio 中的项目设置不正确。我建议阅读 this 文章,了解如何使用 llvm 正确设置 visual studio。然后,我查看了万花筒教程的官方 vs 项目并复制了设置和属性(不仅仅是包含路径...)。