Fix forward references in LLVM constants block

This commit is contained in:
baldurk
2020-10-20 14:33:46 +01:00
parent ebafbdb184
commit 17e80ae9cd
@@ -375,14 +375,17 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
{
const Constant *member = getConstant(m);
if(member)
if(member && member->type)
{
v.members.push_back(*member);
}
else
{
v.members.push_back(Constant());
RDCERR("Index %llu out of bounds for constants array", m);
Constant c;
c.type = NULL;
c.val.u64v[0] = m;
v.members.push_back(c);
RDCWARN("Index %llu out of bounds for constants array, possible forward reference", m);
}
}
}
@@ -962,6 +965,37 @@ Program::Program(const byte *bytes, size_t length)
m_Constants.push_back(v);
});
}
// post-patch up contants with members that are references to future constants (blech!)
for(Constant &c : m_Constants)
{
if(c.members.empty())
continue;
for(Constant &m : c.members)
{
if(m.type == NULL)
{
if(m.val.u64v[0] > 0)
{
size_t idx = (size_t)m.val.u64v[0];
if(idx < m_Constants.size())
{
m = m_Constants[idx];
}
else
{
m = Constant();
RDCERR("Couldn't resolve constant %zu", idx);
}
}
else
{
RDCERR("Unexpected member with no type but no forward-index constant value");
}
}
}
}
}
else if(IS_KNOWN(rootchild.id, KnownBlocks::VALUE_SYMTAB_BLOCK))
{
@@ -1145,6 +1179,29 @@ Program::Program(const byte *bytes, size_t length)
});
}
// post-patch up contants with members that are references to future constants
// (blech!)
for(Constant &c : f.constants)
{
if(c.members.empty())
continue;
for(Constant &m : c.members)
{
if(m.type == NULL)
{
if(m.val.u64v[0] > 0)
{
m = *getConstant(m.val.u64v[0]);
}
else
{
RDCERR("Unexpected member with no type but no forward-index constant value");
}
}
}
}
instrSymbolStart = m_Symbols.size();
}
else if(IS_KNOWN(funcChild.id, KnownBlocks::METADATA_BLOCK))