diff options
author | Sebastian Neubauer <Sebastian.Neubauer@amd.com> | 2023-01-17 13:18:26 +0100 |
---|---|---|
committer | Sebastian Neubauer <Sebastian.Neubauer@amd.com> | 2023-01-17 13:19:40 +0100 |
commit | b56df190b01335506ce30a4559d880da76d1a181 (patch) | |
tree | 8ca17a41546fce4dd55b027676367b4383514390 /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | 53ac16d8445f1d5716441dfbae1c94bfb31511b8 (diff) | |
download | llvm-b56df190b01335506ce30a4559d880da76d1a181.zip llvm-b56df190b01335506ce30a4559d880da76d1a181.tar.gz llvm-b56df190b01335506ce30a4559d880da76d1a181.tar.bz2 |
[BitcodeReader] Allow reading pointer types from old IR
When opaque pointers are enabled and old IR with typed pointers is read,
the BitcodeReader automatically upgrades all typed pointers to opaque
pointers. This is a lossy conversion, i.e. when a function argument is a
pointer and unused, it’s impossible to reconstruct the original type
behind the pointer.
There are cases where the type information of pointers is needed. One is
reading DXIL, which is bitcode of old LLVM IR and makes a lot of use of
pointers in function signatures.
We’d like to keep using up-to-date llvm to read in and process DXIL, so
in the face of opaque pointers, we need some way to access the type
information of pointers from the read bitcode.
This patch allows extracting type information by supplying functions to
parseBitcodeFile that get called for each function signature or metadata
value. The function can access the type information via the reader’s
type IDs and the getTypeByID and getContainedTypeID functions.
The tests exemplarily shows how type info from pointers can be stored in
metadata for use after the BitcodeReader finished.
Differential Revision: https://reviews.llvm.org/D127728
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 75 |
1 files changed, 45 insertions, 30 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index aa33006..0a346e3 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -674,6 +674,8 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { std::vector<std::string> BundleTags; SmallVector<SyncScope::ID, 8> SSIDs; + std::optional<ValueTypeCallbackTy> ValueTypeCallback; + public: BitcodeReader(BitstreamCursor Stream, StringRef Strtab, StringRef ProducerIdentification, LLVMContext &Context); @@ -686,9 +688,8 @@ public: /// Main interface to parsing a bitcode buffer. /// \returns true if an error occurred. - Error parseBitcodeInto( - Module *M, bool ShouldLazyLoadMetadata, bool IsImporting, - DataLayoutCallbackTy DataLayoutCallback); + Error parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata, + bool IsImporting, ParserCallbacks Callbacks = {}); static uint64_t decodeSignRotatedValue(uint64_t V); @@ -709,6 +710,7 @@ private: unsigned getContainedTypeID(unsigned ID, unsigned Idx = 0); unsigned getVirtualTypeID(Type *Ty, ArrayRef<unsigned> ContainedTypeIDs = {}); + void callValueTypeCallback(Value *F, unsigned TypeID); Expected<Value *> materializeValue(unsigned ValID, BasicBlock *InsertBB); Expected<Constant *> getValueForInitializer(unsigned ID); @@ -819,11 +821,8 @@ private: /// a corresponding error code. Error parseAlignmentValue(uint64_t Exponent, MaybeAlign &Alignment); Error parseAttrKind(uint64_t Code, Attribute::AttrKind *Kind); - Error parseModule( - uint64_t ResumeBit, bool ShouldLazyLoadMetadata = false, - DataLayoutCallbackTy DataLayoutCallback = [](StringRef, StringRef) { - return std::nullopt; - }); + Error parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata = false, + ParserCallbacks Callbacks = {}); Error parseComdatRecord(ArrayRef<uint64_t> Record); Error parseGlobalVarRecord(ArrayRef<uint64_t> Record); @@ -3919,6 +3918,14 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) { return Error::success(); } +void BitcodeReader::callValueTypeCallback(Value *F, unsigned TypeID) { + if (ValueTypeCallback) { + (*ValueTypeCallback)( + F, TypeID, [this](unsigned I) { return getTypeByID(I); }, + [this](unsigned I, unsigned J) { return getContainedTypeID(I, J); }); + } +} + Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) { // v1: [type, callingconv, isproto, linkage, paramattr, alignment, section, // visibility, gc, unnamed_addr, prologuedata, dllstorageclass, comdat, @@ -3963,6 +3970,7 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) { uint64_t RawLinkage = Record[3]; Func->setLinkage(getDecodedLinkage(RawLinkage)); Func->setAttributes(getAttributes(Record[4])); + callValueTypeCallback(Func, FTyID); // Upgrade any old-style byval or sret without a type by propagating the // argument's pointee type. There should be no opaque pointers where the byval @@ -4180,7 +4188,8 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( Error BitcodeReader::parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata, - DataLayoutCallbackTy DataLayoutCallback) { + ParserCallbacks Callbacks) { + this->ValueTypeCallback = std::move(Callbacks.ValueType); if (ResumeBit) { if (Error JumpFailed = Stream.JumpToBit(ResumeBit)) return JumpFailed; @@ -4210,9 +4219,11 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit, TentativeDataLayoutStr, TheModule->getTargetTriple()); // Apply override - if (auto LayoutOverride = DataLayoutCallback(TheModule->getTargetTriple(), - TentativeDataLayoutStr)) - TentativeDataLayoutStr = *LayoutOverride; + if (Callbacks.DataLayout) { + if (auto LayoutOverride = (*Callbacks.DataLayout)( + TheModule->getTargetTriple(), TentativeDataLayoutStr)) + TentativeDataLayoutStr = *LayoutOverride; + } // Now the layout string is finalized in TentativeDataLayoutStr. Parse it. Expected<DataLayout> MaybeDL = DataLayout::parse(TentativeDataLayoutStr); @@ -4477,16 +4488,22 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit, } Record.clear(); } + this->ValueTypeCallback = std::nullopt; return Error::success(); } Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata, bool IsImporting, - DataLayoutCallbackTy DataLayoutCallback) { + ParserCallbacks Callbacks) { TheModule = M; - MDLoader = MetadataLoader(Stream, *M, ValueList, IsImporting, - [&](unsigned ID) { return getTypeByID(ID); }); - return parseModule(0, ShouldLazyLoadMetadata, DataLayoutCallback); + MetadataLoaderCallbacks MDCallbacks; + MDCallbacks.GetTypeByID = [&](unsigned ID) { return getTypeByID(ID); }; + MDCallbacks.GetContainedTypeID = [&](unsigned I, unsigned J) { + return getContainedTypeID(I, J); + }; + MDCallbacks.MDType = Callbacks.MDType; + MDLoader = MetadataLoader(Stream, *M, ValueList, IsImporting, MDCallbacks); + return parseModule(0, ShouldLazyLoadMetadata, Callbacks); } Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) { @@ -7919,7 +7936,7 @@ llvm::getBitcodeFileContents(MemoryBufferRef Buffer) { Expected<std::unique_ptr<Module>> BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, bool ShouldLazyLoadMetadata, bool IsImporting, - DataLayoutCallbackTy DataLayoutCallback) { + ParserCallbacks Callbacks) { BitstreamCursor Stream(Buffer); std::string ProducerIdentification; @@ -7942,7 +7959,7 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, // Delay parsing Metadata if ShouldLazyLoadMetadata is true. if (Error Err = R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata, - IsImporting, DataLayoutCallback)) + IsImporting, Callbacks)) return std::move(Err); if (MaterializeAll) { @@ -7959,10 +7976,9 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, Expected<std::unique_ptr<Module>> BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata, - bool IsImporting, - DataLayoutCallbackTy DataLayoutCallback) { + bool IsImporting, ParserCallbacks Callbacks) { return getModuleImpl(Context, false, ShouldLazyLoadMetadata, IsImporting, - DataLayoutCallback); + Callbacks); } // Parse the specified bitcode buffer and merge the index into CombinedIndex. @@ -8109,41 +8125,40 @@ static Expected<BitcodeModule> getSingleModule(MemoryBufferRef Buffer) { Expected<std::unique_ptr<Module>> llvm::getLazyBitcodeModule(MemoryBufferRef Buffer, LLVMContext &Context, bool ShouldLazyLoadMetadata, bool IsImporting, - DataLayoutCallbackTy DataLayoutCallback) { + ParserCallbacks Callbacks) { Expected<BitcodeModule> BM = getSingleModule(Buffer); if (!BM) return BM.takeError(); return BM->getLazyModule(Context, ShouldLazyLoadMetadata, IsImporting, - DataLayoutCallback); + Callbacks); } Expected<std::unique_ptr<Module>> llvm::getOwningLazyBitcodeModule( std::unique_ptr<MemoryBuffer> &&Buffer, LLVMContext &Context, - bool ShouldLazyLoadMetadata, bool IsImporting) { + bool ShouldLazyLoadMetadata, bool IsImporting, ParserCallbacks Callbacks) { auto MOrErr = getLazyBitcodeModule(*Buffer, Context, ShouldLazyLoadMetadata, - IsImporting); + IsImporting, Callbacks); if (MOrErr) (*MOrErr)->setOwnedMemoryBuffer(std::move(Buffer)); return MOrErr; } Expected<std::unique_ptr<Module>> -BitcodeModule::parseModule(LLVMContext &Context, - DataLayoutCallbackTy DataLayoutCallback) { - return getModuleImpl(Context, true, false, false, DataLayoutCallback); +BitcodeModule::parseModule(LLVMContext &Context, ParserCallbacks Callbacks) { + return getModuleImpl(Context, true, false, false, Callbacks); // TODO: Restore the use-lists to the in-memory state when the bitcode was // written. We must defer until the Module has been fully materialized. } Expected<std::unique_ptr<Module>> llvm::parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, - DataLayoutCallbackTy DataLayoutCallback) { + ParserCallbacks Callbacks) { Expected<BitcodeModule> BM = getSingleModule(Buffer); if (!BM) return BM.takeError(); - return BM->parseModule(Context, DataLayoutCallback); + return BM->parseModule(Context, Callbacks); } Expected<std::string> llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer) { |