#include "ValueList.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <limits>
#include <utility>
using namespace llvm;
namespace llvm {
namespace {
class ConstantPlaceHolder : public ConstantExpr {
public:
explicit ConstantPlaceHolder(Type *Ty, LLVMContext &Context)
: ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
}
ConstantPlaceHolder &operator=(const ConstantPlaceHolder &) = delete;
void *operator new(size_t s) { return User::operator new(s, 1); }
static bool classof(const Value *V) {
return isa<ConstantExpr>(V) &&
cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
}
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
}
template <>
struct OperandTraits<ConstantPlaceHolder>
: public FixedNumOperandTraits<ConstantPlaceHolder, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
}
void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
if (Idx == size()) {
push_back(V);
return;
}
if (Idx >= size())
resize(Idx + 1);
WeakTrackingVH &OldV = ValuePtrs[Idx];
if (!OldV) {
OldV = V;
return;
}
if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
ResolveConstants.push_back(std::make_pair(PHC, Idx));
OldV = V;
} else {
Value *PrevVal = OldV;
OldV->replaceAllUsesWith(V);
PrevVal->deleteValue();
}
}
Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) {
if (Idx >= size())
resize(Idx + 1);
if (Value *V = ValuePtrs[Idx]) {
if (Ty != V->getType())
report_fatal_error("Type mismatch in constant table!");
return cast<Constant>(V);
}
Constant *C = new ConstantPlaceHolder(Ty, Context);
ValuePtrs[Idx] = C;
return C;
}
Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
if (Idx == std::numeric_limits<unsigned>::max())
return nullptr;
if (Idx >= size())
resize(Idx + 1);
if (Value *V = ValuePtrs[Idx]) {
if (Ty && Ty != V->getType())
return nullptr;
return V;
}
if (!Ty)
return nullptr;
Value *V = new Argument(Ty);
ValuePtrs[Idx] = V;
return V;
}
void BitcodeReaderValueList::resolveConstantForwardRefs() {
llvm::sort(ResolveConstants.begin(), ResolveConstants.end());
SmallVector<Constant *, 64> NewOps;
while (!ResolveConstants.empty()) {
Value *RealVal = operator[](ResolveConstants.back().second);
Constant *Placeholder = ResolveConstants.back().first;
ResolveConstants.pop_back();
while (!Placeholder->use_empty()) {
auto UI = Placeholder->user_begin();
User *U = *UI;
if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
UI.getUse().set(RealVal);
continue;
}
Constant *UserC = cast<Constant>(U);
for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); I != E;
++I) {
Value *NewOp;
if (!isa<ConstantPlaceHolder>(*I)) {
NewOp = *I;
} else if (*I == Placeholder) {
NewOp = RealVal;
} else {
ResolveConstantsTy::iterator It = std::lower_bound(
ResolveConstants.begin(), ResolveConstants.end(),
std::pair<Constant *, unsigned>(cast<Constant>(*I), 0));
assert(It != ResolveConstants.end() && It->first == *I);
NewOp = operator[](It->second);
}
NewOps.push_back(cast<Constant>(NewOp));
}
Constant *NewC;
if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
NewC = ConstantArray::get(UserCA->getType(), NewOps);
} else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
NewC = ConstantStruct::get(UserCS->getType(), NewOps);
} else if (isa<ConstantVector>(UserC)) {
NewC = ConstantVector::get(NewOps);
} else {
assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
}
UserC->replaceAllUsesWith(NewC);
UserC->destroyConstant();
NewOps.clear();
}
Placeholder->replaceAllUsesWith(RealVal);
Placeholder->deleteValue();
}
}