C++ 在LLVM中调用CreatePHI()时出错

C++ 在LLVM中调用CreatePHI()时出错,c++,llvm,C++,Llvm,我调试了两天!在搜索官方文档和谷歌后,找不到任何原因或信息 是LLVM的错误吗?请帮帮我 (LLVM版本:3.7.1) 错误信息: Assertion failed: HasHungOffUses && "alloc must have hung off uses", , file I:\GitHub\Def\llvm\lib\IR\User.cpp, line 44 守则: Value* ASTIf::codegen(Gen & gen) { // if

我调试了两天!在搜索官方文档和谷歌后,找不到任何原因或信息

是LLVM的错误吗?请帮帮我

(LLVM版本:3.7.1)

错误信息:

Assertion failed: HasHungOffUses && "alloc must have hung off uses", , file I:\GitHub\Def\llvm\lib\IR\User.cpp, line 44
守则:

Value* ASTIf::codegen(Gen & gen)
{
    // if 
    Value *v_ret(nullptr);
    auto *thefunc = gen.builder.GetInsertBlock()->getParent();

    Value *v_cond = cond->codegen(gen);
    auto *b_then = BasicBlock::Create(gen.context, "then", thefunc);
    auto *b_else = BasicBlock::Create(gen.context, "else", thefunc);
    auto *b_merge = BasicBlock::Create(gen.context, "ifcont", thefunc);

    // 跳转分支
    gen.builder.CreateCondBr(v_cond, b_then, b_else);

    // then block
    gen.builder.SetInsertPoint(b_then);
    Value *v_then = pthen->codegen(gen);
    gen.builder.CreateBr(b_merge);
    b_then = gen.builder.GetInsertBlock();

    // else block
    gen.builder.SetInsertPoint(b_else);
    Value *v_else = pelse ? pelse->codegen(gen) : nullptr;
    gen.builder.CreateBr(b_merge);
    b_else = gen.builder.GetInsertBlock();

    // merge block
    gen.builder.SetInsertPoint(b_merge);
    // if error: HasHungOffUses
    if (canphi) {

        PHINode *phi = gen.builder.CreatePHI(  //////////  error line   /////////
            v_then->getType(), 2, "iftmp");
        phi->addIncoming(v_then, b_then);
        phi->addIncoming(v_else, b_else);
        v_ret = phi;
    }

    return v_ret;
}
添加注释通知的调用堆栈:


请关闭VS的SDL检查(配置属性->C/C++->常规->SDL检查)。 断言检查由
运算符new
设置的位标志
hashungoffuse
,当SDL打开时,该位标志可能会被覆盖

gen.builder.CreatePHI
调用
User::operator new(size\u t size)
,它将
hashungoffuse分配给分配的内存,但不初始化。它应该保持它之前的状态

下面的代码来自LLVM svn 266960(开发中的3.9.0)

void User::allochungoffuse(未签名的N,bool-IsPhi){
断言(HasHungOffUses&“alloc必须挂起使用”);
静态断言(AlignOf::Alignment>=AlignOf::Alignment,
“对齐不足以满足‘悬挂使用’工件”);
静态断言(AlignOf::Alignment>=
AlignOf::Alignment,
“对齐不足以满足‘悬挂使用’工件”);
//分配使用数组,后跟一个指针(设置底部位)到
//用户。
size\u t size=N*sizeof(Use)+sizeof(Use::UserRef);
如果(IsPhi)
大小+=N*sizeof(基本块*);
使用*Begin=static_cast(::操作符new(size));
使用*End=Begin+N;
(无效)新(最终)用途::UserRef(const_cast(this),1);
setOperationList(使用::initTags(开始,结束));
}

如果打开sdl,op new分配的内存似乎在ctor之前被memset设置为0,这会给出
HasHungOffUses
一个
false
值,因此断言失败。

我想我们需要知道命中该断言的条件是什么?什么是调用堆栈?在您的情况下,
pelse
是什么?我认为给
addIncoming
一个
nullptr
不是一个好主意。查看代码对我来说很健壮,可能您的非llvm代码中的某个地方有s堆损坏。谢谢,事实正是如此:
操作符new
设置
hashungoffuse
标志,但是当流到达
指令
构造函数时,由于
/sdl
的原因,该标志被重置为0。
void *User::operator new(size_t Size) {
  // Allocate space for a single Use*
  void *Storage = ::operator new(Size + sizeof(Use *));
  Use **HungOffOperandList = static_cast<Use **>(Storage);
  User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1);
  Obj->NumUserOperands = 0;
  Obj->HasHungOffUses = true;
  Obj->HasDescriptor = false;
  *HungOffOperandList = nullptr;
  return Obj;
}
explicit PHINode(Type *Ty, unsigned NumReservedValues,
             const Twine &NameStr = "",
             Instruction *InsertBefore = nullptr)
    : Instruction(Ty, Instruction::PHI, nullptr, 0, InsertBefore),
    ReservedSpace(NumReservedValues) {
setName(NameStr);
allocHungoffUses(ReservedSpace);
}
void User::allocHungoffUses(unsigned N, bool IsPhi) {
assert(HasHungOffUses && "alloc must have hung off uses");
static_assert(AlignOf<Use>::Alignment >= AlignOf<Use::UserRef>::Alignment,
              "Alignment is insufficient for 'hung-off-uses' pieces");
static_assert(AlignOf<Use::UserRef>::Alignment >=
              AlignOf<BasicBlock *>::Alignment,
              "Alignment is insufficient for 'hung-off-uses' pieces");
// Allocate the array of Uses, followed by a pointer (with bottom bit set) to
// the User.
size_t size = N * sizeof(Use) + sizeof(Use::UserRef);
if (IsPhi)
    size += N * sizeof(BasicBlock *);
Use *Begin = static_cast<Use*>(::operator new(size));
Use *End = Begin + N;
(void) new(End) Use::UserRef(const_cast<User*>(this), 1);
setOperandList(Use::initTags(Begin, End));

}