Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1,134 +0,0 @@
//===-- BitReader.cpp -----------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm-c/BitReader.h"
#include "llvm-c/Core.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <string>
using namespace llvm;
/* Builds a module from the bitcode in the specified memory buffer, returning a
reference to the module via the OutModule parameter. Returns 0 on success.
Optionally returns a human-readable error message via OutMessage. */
LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule,
char **OutMessage) {
return LLVMParseBitcodeInContext(LLVMGetGlobalContext(), MemBuf, OutModule,
OutMessage);
}
LLVMBool LLVMParseBitcode2(LLVMMemoryBufferRef MemBuf,
LLVMModuleRef *OutModule) {
return LLVMParseBitcodeInContext2(LLVMGetGlobalContext(), MemBuf, OutModule);
}
LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef,
LLVMMemoryBufferRef MemBuf,
LLVMModuleRef *OutModule,
char **OutMessage) {
MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef();
LLVMContext &Ctx = *unwrap(ContextRef);
Expected<std::unique_ptr<Module>> ModuleOrErr = parseBitcodeFile(Buf, Ctx);
if (Error Err = ModuleOrErr.takeError()) {
std::string Message;
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
Message = EIB.message();
});
if (OutMessage)
*OutMessage = strdup(Message.c_str());
*OutModule = wrap((Module *)nullptr);
return 1;
}
*OutModule = wrap(ModuleOrErr.get().release());
return 0;
}
LLVMBool LLVMParseBitcodeInContext2(LLVMContextRef ContextRef,
LLVMMemoryBufferRef MemBuf,
LLVMModuleRef *OutModule) {
MemoryBufferRef Buf = unwrap(MemBuf)->getMemBufferRef();
LLVMContext &Ctx = *unwrap(ContextRef);
ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
expectedToErrorOrAndEmitErrors(Ctx, parseBitcodeFile(Buf, Ctx));
if (ModuleOrErr.getError()) {
*OutModule = wrap((Module *)nullptr);
return 1;
}
*OutModule = wrap(ModuleOrErr.get().release());
return 0;
}
/* Reads a module from the specified path, returning via the OutModule parameter
a module provider which performs lazy deserialization. Returns 0 on success.
Optionally returns a human-readable error message via OutMessage. */
LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef,
LLVMMemoryBufferRef MemBuf,
LLVMModuleRef *OutM, char **OutMessage) {
LLVMContext &Ctx = *unwrap(ContextRef);
std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf));
Expected<std::unique_ptr<Module>> ModuleOrErr =
getOwningLazyBitcodeModule(std::move(Owner), Ctx);
// Release the buffer if we didn't take ownership of it since we never owned
// it anyway.
(void)Owner.release();
if (Error Err = ModuleOrErr.takeError()) {
std::string Message;
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
Message = EIB.message();
});
if (OutMessage)
*OutMessage = strdup(Message.c_str());
*OutM = wrap((Module *)nullptr);
return 1;
}
*OutM = wrap(ModuleOrErr.get().release());
return 0;
}
LLVMBool LLVMGetBitcodeModuleInContext2(LLVMContextRef ContextRef,
LLVMMemoryBufferRef MemBuf,
LLVMModuleRef *OutM) {
LLVMContext &Ctx = *unwrap(ContextRef);
std::unique_ptr<MemoryBuffer> Owner(unwrap(MemBuf));
ErrorOr<std::unique_ptr<Module>> ModuleOrErr = expectedToErrorOrAndEmitErrors(
Ctx, getOwningLazyBitcodeModule(std::move(Owner), Ctx));
Owner.release();
if (ModuleOrErr.getError()) {
*OutM = wrap((Module *)nullptr);
return 1;
}
*OutM = wrap(ModuleOrErr.get().release());
return 0;
}
LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM,
char **OutMessage) {
return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM,
OutMessage);
}
LLVMBool LLVMGetBitcodeModule2(LLVMMemoryBufferRef MemBuf,
LLVMModuleRef *OutM) {
return LLVMGetBitcodeModuleInContext2(LLVMGetGlobalContext(), MemBuf, OutM);
}

View File

@ -1 +0,0 @@
945ac451536862033d0336f38be662d9657a3e72

View File

@ -1,390 +0,0 @@
//===- BitstreamReader.cpp - BitstreamReader implementation ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <string>
using namespace llvm;
//===----------------------------------------------------------------------===//
// BitstreamCursor implementation
//===----------------------------------------------------------------------===//
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
/// the block, and return true if the block has an error.
bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
// Save the current block's state on BlockScope.
BlockScope.push_back(Block(CurCodeSize));
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
// Add the abbrevs specific to this block to the CurAbbrevs list.
if (BlockInfo) {
if (const BitstreamBlockInfo::BlockInfo *Info =
BlockInfo->getBlockInfo(BlockID)) {
CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
Info->Abbrevs.end());
}
}
// Get the codesize of this block.
CurCodeSize = ReadVBR(bitc::CodeLenWidth);
// We can't read more than MaxChunkSize at a time
if (CurCodeSize > MaxChunkSize)
return true;
SkipToFourByteBoundary();
unsigned NumWords = Read(bitc::BlockSizeWidth);
if (NumWordsP) *NumWordsP = NumWords;
// Validate that this block is sane.
return CurCodeSize == 0 || AtEndOfStream();
}
static uint64_t readAbbreviatedField(BitstreamCursor &Cursor,
const BitCodeAbbrevOp &Op) {
assert(!Op.isLiteral() && "Not to be used with literals!");
// Decode the value as we are commanded.
switch (Op.getEncoding()) {
case BitCodeAbbrevOp::Array:
case BitCodeAbbrevOp::Blob:
llvm_unreachable("Should not reach here");
case BitCodeAbbrevOp::Fixed:
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
return Cursor.Read((unsigned)Op.getEncodingData());
case BitCodeAbbrevOp::VBR:
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
return Cursor.ReadVBR64((unsigned)Op.getEncodingData());
case BitCodeAbbrevOp::Char6:
return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6));
}
llvm_unreachable("invalid abbreviation encoding");
}
static void skipAbbreviatedField(BitstreamCursor &Cursor,
const BitCodeAbbrevOp &Op) {
assert(!Op.isLiteral() && "Not to be used with literals!");
// Decode the value as we are commanded.
switch (Op.getEncoding()) {
case BitCodeAbbrevOp::Array:
case BitCodeAbbrevOp::Blob:
llvm_unreachable("Should not reach here");
case BitCodeAbbrevOp::Fixed:
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
Cursor.Read((unsigned)Op.getEncodingData());
break;
case BitCodeAbbrevOp::VBR:
assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
Cursor.ReadVBR64((unsigned)Op.getEncodingData());
break;
case BitCodeAbbrevOp::Char6:
Cursor.Read(6);
break;
}
}
/// skipRecord - Read the current record and discard it.
unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
// Skip unabbreviated records by reading past their entries.
if (AbbrevID == bitc::UNABBREV_RECORD) {
unsigned Code = ReadVBR(6);
unsigned NumElts = ReadVBR(6);
for (unsigned i = 0; i != NumElts; ++i)
(void)ReadVBR64(6);
return Code;
}
const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0);
unsigned Code;
if (CodeOp.isLiteral())
Code = CodeOp.getLiteralValue();
else {
if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
report_fatal_error("Abbreviation starts with an Array or a Blob");
Code = readAbbreviatedField(*this, CodeOp);
}
for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) {
const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
if (Op.isLiteral())
continue;
if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
Op.getEncoding() != BitCodeAbbrevOp::Blob) {
skipAbbreviatedField(*this, Op);
continue;
}
if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
// Array case. Read the number of elements as a vbr6.
unsigned NumElts = ReadVBR(6);
// Get the element encoding.
assert(i+2 == e && "array op not second to last?");
const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
// Read all the elements.
// Decode the value as we are commanded.
switch (EltEnc.getEncoding()) {
default:
report_fatal_error("Array element type can't be an Array or a Blob");
case BitCodeAbbrevOp::Fixed:
assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
JumpToBit(GetCurrentBitNo() + NumElts * EltEnc.getEncodingData());
break;
case BitCodeAbbrevOp::VBR:
assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
for (; NumElts; --NumElts)
ReadVBR64((unsigned)EltEnc.getEncodingData());
break;
case BitCodeAbbrevOp::Char6:
JumpToBit(GetCurrentBitNo() + NumElts * 6);
break;
}
continue;
}
assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
// Blob case. Read the number of bytes as a vbr6.
unsigned NumElts = ReadVBR(6);
SkipToFourByteBoundary(); // 32-bit alignment
// Figure out where the end of this blob will be including tail padding.
size_t NewEnd = GetCurrentBitNo()+((NumElts+3)&~3)*8;
// If this would read off the end of the bitcode file, just set the
// record to empty and return.
if (!canSkipToPos(NewEnd/8)) {
skipToEnd();
break;
}
// Skip over the blob.
JumpToBit(NewEnd);
}
return Code;
}
unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
SmallVectorImpl<uint64_t> &Vals,
StringRef *Blob) {
if (AbbrevID == bitc::UNABBREV_RECORD) {
unsigned Code = ReadVBR(6);
unsigned NumElts = ReadVBR(6);
for (unsigned i = 0; i != NumElts; ++i)
Vals.push_back(ReadVBR64(6));
return Code;
}
const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
// Read the record code first.
assert(Abbv->getNumOperandInfos() != 0 && "no record code in abbreviation?");
const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0);
unsigned Code;
if (CodeOp.isLiteral())
Code = CodeOp.getLiteralValue();
else {
if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
report_fatal_error("Abbreviation starts with an Array or a Blob");
Code = readAbbreviatedField(*this, CodeOp);
}
for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
if (Op.isLiteral()) {
Vals.push_back(Op.getLiteralValue());
continue;
}
if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
Op.getEncoding() != BitCodeAbbrevOp::Blob) {
Vals.push_back(readAbbreviatedField(*this, Op));
continue;
}
if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
// Array case. Read the number of elements as a vbr6.
unsigned NumElts = ReadVBR(6);
// Get the element encoding.
if (i + 2 != e)
report_fatal_error("Array op not second to last");
const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
if (!EltEnc.isEncoding())
report_fatal_error(
"Array element type has to be an encoding of a type");
// Read all the elements.
switch (EltEnc.getEncoding()) {
default:
report_fatal_error("Array element type can't be an Array or a Blob");
case BitCodeAbbrevOp::Fixed:
for (; NumElts; --NumElts)
Vals.push_back(Read((unsigned)EltEnc.getEncodingData()));
break;
case BitCodeAbbrevOp::VBR:
for (; NumElts; --NumElts)
Vals.push_back(ReadVBR64((unsigned)EltEnc.getEncodingData()));
break;
case BitCodeAbbrevOp::Char6:
for (; NumElts; --NumElts)
Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6)));
}
continue;
}
assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
// Blob case. Read the number of bytes as a vbr6.
unsigned NumElts = ReadVBR(6);
SkipToFourByteBoundary(); // 32-bit alignment
// Figure out where the end of this blob will be including tail padding.
size_t CurBitPos = GetCurrentBitNo();
size_t NewEnd = CurBitPos+((NumElts+3)&~3)*8;
// If this would read off the end of the bitcode file, just set the
// record to empty and return.
if (!canSkipToPos(NewEnd/8)) {
Vals.append(NumElts, 0);
skipToEnd();
break;
}
// Otherwise, inform the streamer that we need these bytes in memory. Skip
// over tail padding first, in case jumping to NewEnd invalidates the Blob
// pointer.
JumpToBit(NewEnd);
const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts);
// If we can return a reference to the data, do so to avoid copying it.
if (Blob) {
*Blob = StringRef(Ptr, NumElts);
} else {
// Otherwise, unpack into Vals with zero extension.
for (; NumElts; --NumElts)
Vals.push_back((unsigned char)*Ptr++);
}
}
return Code;
}
void BitstreamCursor::ReadAbbrevRecord() {
auto Abbv = std::make_shared<BitCodeAbbrev>();
unsigned NumOpInfo = ReadVBR(5);
for (unsigned i = 0; i != NumOpInfo; ++i) {
bool IsLiteral = Read(1);
if (IsLiteral) {
Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8)));
continue;
}
BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3);
if (BitCodeAbbrevOp::hasEncodingData(E)) {
uint64_t Data = ReadVBR64(5);
// As a special case, handle fixed(0) (i.e., a fixed field with zero bits)
// and vbr(0) as a literal zero. This is decoded the same way, and avoids
// a slow path in Read() to have to handle reading zero bits.
if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&
Data == 0) {
Abbv->Add(BitCodeAbbrevOp(0));
continue;
}
if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&
Data > MaxChunkSize)
report_fatal_error(
"Fixed or VBR abbrev record with size > MaxChunkData");
Abbv->Add(BitCodeAbbrevOp(E, Data));
} else
Abbv->Add(BitCodeAbbrevOp(E));
}
if (Abbv->getNumOperandInfos() == 0)
report_fatal_error("Abbrev record with no operands");
CurAbbrevs.push_back(std::move(Abbv));
}
Optional<BitstreamBlockInfo>
BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None;
BitstreamBlockInfo NewBlockInfo;
SmallVector<uint64_t, 64> Record;
BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr;
// Read all the records for this module.
while (true) {
BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
return None;
case llvm::BitstreamEntry::EndBlock:
return std::move(NewBlockInfo);
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
}
// Read abbrev records, associate them with CurBID.
if (Entry.ID == bitc::DEFINE_ABBREV) {
if (!CurBlockInfo) return None;
ReadAbbrevRecord();
// ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the
// appropriate BlockInfo.
CurBlockInfo->Abbrevs.push_back(std::move(CurAbbrevs.back()));
CurAbbrevs.pop_back();
continue;
}
// Read a record.
Record.clear();
switch (readRecord(Entry.ID, Record)) {
default: break; // Default behavior, ignore unknown content.
case bitc::BLOCKINFO_CODE_SETBID:
if (Record.size() < 1) return None;
CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
break;
case bitc::BLOCKINFO_CODE_BLOCKNAME: {
if (!CurBlockInfo) return None;
if (!ReadBlockInfoNames)
break; // Ignore name.
std::string Name;
for (unsigned i = 0, e = Record.size(); i != e; ++i)
Name += (char)Record[i];
CurBlockInfo->Name = Name;
break;
}
case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
if (!CurBlockInfo) return None;
if (!ReadBlockInfoNames)
break; // Ignore name.
std::string Name;
for (unsigned i = 1, e = Record.size(); i != e; ++i)
Name += (char)Record[i];
CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0],
Name));
break;
}
}
}
}

View File

@ -1,13 +0,0 @@
add_llvm_library(LLVMBitReader
BitReader.cpp
BitcodeReader.cpp
BitstreamReader.cpp
MetadataLoader.cpp
ValueList.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Bitcode
DEPENDS
intrinsics_gen
)

View File

@ -1,22 +0,0 @@
;===- ./lib/Bitcode/Reader/LLVMBuild.txt -----------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = BitReader
parent = Bitcode
required_libraries = Core Support

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +0,0 @@
//===-- Bitcode/Reader/MetadataLoader.h - Load Metadatas -------*- C++ -*-====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class handles loading Metadatas.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_BITCODE_READER_METADATALOADER_H
#define LLVM_LIB_BITCODE_READER_METADATALOADER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include <functional>
#include <memory>
namespace llvm {
class BitcodeReaderValueList;
class BitstreamCursor;
class DISubprogram;
class Error;
class Function;
class Instruction;
class Metadata;
class MDNode;
class Module;
class Type;
/// Helper class that handles loading Metadatas and keeping them available.
class MetadataLoader {
class MetadataLoaderImpl;
std::unique_ptr<MetadataLoaderImpl> Pimpl;
Error parseMetadata(bool ModuleLevel);
public:
~MetadataLoader();
MetadataLoader(BitstreamCursor &Stream, Module &TheModule,
BitcodeReaderValueList &ValueList, bool IsImporting,
std::function<Type *(unsigned)> getTypeByID);
MetadataLoader &operator=(MetadataLoader &&);
MetadataLoader(MetadataLoader &&);
// Parse a module metadata block
Error parseModuleMetadata() { return parseMetadata(true); }
// Parse a function metadata block
Error parseFunctionMetadata() { return parseMetadata(false); }
/// Set the mode to strip TBAA metadata on load.
void setStripTBAA(bool StripTBAA = true);
/// Return true if the Loader is stripping TBAA metadata.
bool isStrippingTBAA();
// Return true there are remaining unresolved forward references.
bool hasFwdRefs() const;
/// Return the given metadata, creating a replaceable forward reference if
/// necessary.
Metadata *getMetadataFwdRefOrLoad(unsigned Idx);
MDNode *getMDNodeFwdRefOrNull(unsigned Idx);
/// Return the DISubprogra metadata for a Function if any, null otherwise.
DISubprogram *lookupSubprogramForFunction(Function *F);
/// Parse a `METADATA_ATTACHMENT` block for a function.
Error parseMetadataAttachment(
Function &F, const SmallVectorImpl<Instruction *> &InstructionList);
/// Parse a `METADATA_KIND` block for the current module.
Error parseMetadataKinds();
unsigned size() const;
void shrinkTo(unsigned N);
/// Perform bitcode upgrades on llvm.dbg.* calls.
void upgradeDebugIntrinsics(Function &F);
};
}
#endif // LLVM_LIB_BITCODE_READER_METADATALOADER_H

View File

@ -1,216 +0,0 @@
//===- ValueList.cpp - Internal BitcodeReader implementation --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#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 {
/// \brief A class for maintaining the slot number definition
/// as a placeholder for the actual definition for forward constants defs.
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;
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
/// \brief Methods to support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return isa<ConstantExpr>(V) &&
cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
} // end anonymous namespace
// FIXME: can we inherit this from ConstantExpr?
template <>
struct OperandTraits<ConstantPlaceHolder>
: public FixedNumOperandTraits<ConstantPlaceHolder, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
} // end namespace llvm
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;
}
// Handle constants and non-constants (e.g. instrs) differently for
// efficiency.
if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
ResolveConstants.push_back(std::make_pair(PHC, Idx));
OldV = V;
} else {
// If there was a forward reference to this value, replace it.
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);
}
// Create and return a placeholder, which will later be RAUW'd.
Constant *C = new ConstantPlaceHolder(Ty, Context);
ValuePtrs[Idx] = C;
return C;
}
Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
// Bail out for a clearly invalid value. This would make us call resize(0)
if (Idx == std::numeric_limits<unsigned>::max())
return nullptr;
if (Idx >= size())
resize(Idx + 1);
if (Value *V = ValuePtrs[Idx]) {
// If the types don't match, it's invalid.
if (Ty && Ty != V->getType())
return nullptr;
return V;
}
// No type specified, must be invalid reference.
if (!Ty)
return nullptr;
// Create and return a placeholder, which will later be RAUW'd.
Value *V = new Argument(Ty);
ValuePtrs[Idx] = V;
return V;
}
/// Once all constants are read, this method bulk resolves any forward
/// references. The idea behind this is that we sometimes get constants (such
/// as large arrays) which reference *many* forward ref constants. Replacing
/// each of these causes a lot of thrashing when building/reuniquing the
/// constant. Instead of doing this, we look at all the uses and rewrite all
/// the place holders at once for any constant that uses a placeholder.
void BitcodeReaderValueList::resolveConstantForwardRefs() {
// Sort the values by-pointer so that they are efficient to look up with a
// binary search.
std::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();
// Loop over all users of the placeholder, updating them to reference the
// new value. If they reference more than one placeholder, update them all
// at once.
while (!Placeholder->use_empty()) {
auto UI = Placeholder->user_begin();
User *U = *UI;
// If the using object isn't uniqued, just update the operands. This
// handles instructions and initializers for global variables.
if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
UI.getUse().set(RealVal);
continue;
}
// Otherwise, we have a constant that uses the placeholder. Replace that
// constant with a new constant that has *all* placeholder uses updated.
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)) {
// Not a placeholder reference.
NewOp = *I;
} else if (*I == Placeholder) {
// Common case is that it just references this one placeholder.
NewOp = RealVal;
} else {
// Otherwise, look up the placeholder in ResolveConstants.
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));
}
// Make the new constant.
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();
}
// Update all ValueHandles, they should be the only users at this point.
Placeholder->replaceAllUsesWith(RealVal);
Placeholder->deleteValue();
}
}

View File

@ -1,86 +0,0 @@
//===-- Bitcode/Reader/ValueList.h - Number values --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class gives values and types Unique ID's.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_BITCODE_READER_VALUELIST_H
#define LLVM_LIB_BITCODE_READER_VALUELIST_H
#include "llvm/IR/ValueHandle.h"
#include <cassert>
#include <utility>
#include <vector>
namespace llvm {
class Constant;
class LLVMContext;
class Type;
class Value;
class BitcodeReaderValueList {
std::vector<WeakTrackingVH> ValuePtrs;
/// As we resolve forward-referenced constants, we add information about them
/// to this vector. This allows us to resolve them in bulk instead of
/// resolving each reference at a time. See the code in
/// ResolveConstantForwardRefs for more information about this.
///
/// The key of this vector is the placeholder constant, the value is the slot
/// number that holds the resolved value.
using ResolveConstantsTy = std::vector<std::pair<Constant *, unsigned>>;
ResolveConstantsTy ResolveConstants;
LLVMContext &Context;
public:
BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
~BitcodeReaderValueList() {
assert(ResolveConstants.empty() && "Constants not resolved?");
}
// vector compatibility methods
unsigned size() const { return ValuePtrs.size(); }
void resize(unsigned N) { ValuePtrs.resize(N); }
void push_back(Value *V) { ValuePtrs.emplace_back(V); }
void clear() {
assert(ResolveConstants.empty() && "Constants not resolved?");
ValuePtrs.clear();
}
Value *operator[](unsigned i) const {
assert(i < ValuePtrs.size());
return ValuePtrs[i];
}
Value *back() const { return ValuePtrs.back(); }
void pop_back() { ValuePtrs.pop_back(); }
bool empty() const { return ValuePtrs.empty(); }
void shrinkTo(unsigned N) {
assert(N <= size() && "Invalid shrinkTo request!");
ValuePtrs.resize(N);
}
Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
Value *getValueFwdRef(unsigned Idx, Type *Ty);
void assignValue(Value *V, unsigned Idx);
/// Once all constants are read, this method bulk resolves any forward
/// references.
void resolveConstantForwardRefs();
};
} // end namespace llvm
#endif // LLVM_LIB_BITCODE_READER_VALUELIST_H