llvm.org GIT mirror llvm / cc625c9
Handle forward referenced function when streaming bitcode. Without this the included unit test would assert in assert(BasicBlockFwdRefs.empty() && "Unresolved blockaddress fwd references"); git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239871 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 4 years ago
2 changed file(s) with 84 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
45964596 // External interface
45974597 //===----------------------------------------------------------------------===//
45984598
4599 static ErrorOr>
4600 getBitcodeModuleImpl(std::unique_ptr Streamer, StringRef Name,
4601 BitcodeReader *R, LLVMContext &Context,
4602 bool MaterializeAll, bool ShouldLazyLoadMetadata) {
4603 std::unique_ptr M = make_unique(Name, Context);
4604 M->setMaterializer(R);
4605
4606 auto cleanupOnError = [&](std::error_code EC) {
4607 R->releaseBuffer(); // Never take ownership on error.
4608 return EC;
4609 };
4610
4611 // Delay parsing Metadata if ShouldLazyLoadMetadata is true.
4612 if (std::error_code EC = R->parseBitcodeInto(std::move(Streamer), M.get(),
4613 ShouldLazyLoadMetadata))
4614 return cleanupOnError(EC);
4615
4616 if (MaterializeAll) {
4617 // Read in the entire module, and destroy the BitcodeReader.
4618 if (std::error_code EC = M->materializeAllPermanently())
4619 return cleanupOnError(EC);
4620 } else {
4621 // Resolve forward references from blockaddresses.
4622 if (std::error_code EC = R->materializeForwardReferencedFunctions())
4623 return cleanupOnError(EC);
4624 }
4625 return std::move(M);
4626 }
4627
45994628 /// \brief Get a lazy one-at-time loading module from bitcode.
46004629 ///
46014630 /// This isn't always used in a lazy context. In particular, it's also used by
46094638 LLVMContext &Context, bool MaterializeAll,
46104639 DiagnosticHandlerFunction DiagnosticHandler,
46114640 bool ShouldLazyLoadMetadata = false) {
4612 std::unique_ptr M =
4613 make_unique(Buffer->getBufferIdentifier(), Context);
46144641 BitcodeReader *R =
46154642 new BitcodeReader(Buffer.get(), Context, DiagnosticHandler);
4616 M->setMaterializer(R);
4617
4618 auto cleanupOnError = [&](std::error_code EC) {
4619 R->releaseBuffer(); // Never take ownership on error.
4620 return EC;
4621 };
4622
4623 // Delay parsing Metadata if ShouldLazyLoadMetadata is true.
4624 if (std::error_code EC =
4625 R->parseBitcodeInto(nullptr, M.get(), ShouldLazyLoadMetadata))
4626 return cleanupOnError(EC);
4627
4628 if (MaterializeAll) {
4629 // Read in the entire module, and destroy the BitcodeReader.
4630 if (std::error_code EC = M->materializeAllPermanently())
4631 return EC;
4632 } else {
4633 // Resolve forward references from blockaddresses.
4634 if (std::error_code EC = R->materializeForwardReferencedFunctions())
4635 return cleanupOnError(EC);
4636 }
4643
4644 ErrorOr> Ret =
4645 getBitcodeModuleImpl(nullptr, Buffer->getBufferIdentifier(), R, Context,
4646 MaterializeAll, ShouldLazyLoadMetadata);
4647 if (!Ret)
4648 return Ret;
46374649
46384650 Buffer.release(); // The BitcodeReader owns it now.
4639 return std::move(M);
4651 return Ret;
46404652 }
46414653
46424654 ErrorOr> llvm::getLazyBitcodeModule(
46514663 LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler) {
46524664 std::unique_ptr M = make_unique(Name, Context);
46534665 BitcodeReader *R = new BitcodeReader(Context, DiagnosticHandler);
4654 M->setMaterializer(R);
4655 if (std::error_code EC = R->parseBitcodeInto(std::move(Streamer), M.get()))
4656 return EC;
4657 return std::move(M);
4666
4667 return getBitcodeModuleImpl(std::move(Streamer), Name, R, Context, false,
4668 false);
46584669 }
46594670
46604671 ErrorOr>
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/ADT/SmallString.h"
10 #include "llvm/ADT/STLExtras.h"
1011 #include "llvm/AsmParser/Parser.h"
1112 #include "llvm/Bitcode/BitstreamWriter.h"
1213 #include "llvm/Bitcode/ReaderWriter.h"
1516 #include "llvm/IR/LLVMContext.h"
1617 #include "llvm/IR/Module.h"
1718 #include "llvm/IR/Verifier.h"
19 #include "llvm/Support/DataStream.h"
1820 #include "llvm/Support/Debug.h"
1921 #include "llvm/Support/MemoryBuffer.h"
2022 #include "llvm/Support/SourceMgr.h"
5759 return std::move(ModuleOrErr.get());
5860 }
5961
62 class BufferDataStreamer : public DataStreamer {
63 std::unique_ptr Buffer;
64 unsigned Pos = 0;
65 size_t GetBytes(unsigned char *Out, size_t Len) override {
66 StringRef Buf = Buffer->getBuffer();
67 size_t Left = Buf.size() - Pos;
68 Len = std::min(Left, Len);
69 memcpy(Out, Buffer->getBuffer().substr(Pos).data(), Len);
70 Pos += Len;
71 return Len;
72 }
73
74 public:
75 BufferDataStreamer(std::unique_ptr Buffer)
76 : Buffer(std::move(Buffer)) {}
77 };
78
79 static std::unique_ptr
80 getStreamedModuleFromAssembly(LLVMContext &Context, SmallString<1024> &Mem,
81 const char *Assembly) {
82 writeModuleToBuffer(parseAssembly(Assembly), Mem);
83 std::unique_ptr Buffer =
84 MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
85 auto Streamer = make_unique(std::move(Buffer));
86 ErrorOr> ModuleOrErr =
87 getStreamedBitcodeModule("test", std::move(Streamer), Context);
88 return std::move(ModuleOrErr.get());
89 }
90
91 TEST(BitReaderTest, MateralizeForwardRefWithStream) {
92 SmallString<1024> Mem;
93
94 LLVMContext Context;
95 std::unique_ptr M = getStreamedModuleFromAssembly(
96 Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
97 "define void @func() {\n"
98 " unreachable\n"
99 "bb:\n"
100 " unreachable\n"
101 "}\n");
102 EXPECT_FALSE(M->getFunction("func")->empty());
103 }
104
60105 TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) {
61106 SmallString<1024> Mem;
62107