brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.4 KiB · aea66fc Raw
437 lines · cpp
1//===- llvm/unittest/Bitcode/BitReaderTest.cpp - Tests for BitReader ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "BitReaderTestCode.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/SmallString.h"12#include "llvm/AsmParser/Parser.h"13#include "llvm/Bitcode/BitcodeReader.h"14#include "llvm/Bitcode/BitcodeWriter.h"15#include "llvm/IR/Constants.h"16#include "llvm/IR/InstrTypes.h"17#include "llvm/IR/LLVMContext.h"18#include "llvm/IR/Module.h"19#include "llvm/IR/Verifier.h"20#include "llvm/Support/Debug.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/MemoryBuffer.h"23#include "llvm/Support/SourceMgr.h"24#include "gtest/gtest.h"25 26using namespace llvm;27 28namespace {29 30std::unique_ptr<Module> parseAssembly(LLVMContext &Context,31                                      const char *Assembly) {32  SMDiagnostic Error;33  std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);34 35  std::string ErrMsg;36  raw_string_ostream OS(ErrMsg);37  Error.print("", OS);38 39  // A failure here means that the test itself is buggy.40  if (!M)41    report_fatal_error(ErrMsg.c_str());42 43  return M;44}45 46static void writeModuleToBuffer(std::unique_ptr<Module> Mod,47                                SmallVectorImpl<char> &Buffer) {48  raw_svector_ostream OS(Buffer);49  WriteBitcodeToFile(*Mod, OS);50}51 52static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context,53                                                         SmallString<1024> &Mem,54                                                         const char *Assembly) {55  writeModuleToBuffer(parseAssembly(Context, Assembly), Mem);56  Expected<std::unique_ptr<Module>> ModuleOrErr =57      getLazyBitcodeModule(MemoryBufferRef(Mem.str(), "test"), Context);58  if (!ModuleOrErr)59    report_fatal_error("Could not parse bitcode module");60  return std::move(ModuleOrErr.get());61}62 63// Tests that lazy evaluation can parse functions out of order.64TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {65  SmallString<1024> Mem;66  LLVMContext Context;67  std::unique_ptr<Module> M = getLazyModuleFromAssembly(68      Context, Mem, "define void @f() {\n"69                    "  unreachable\n"70                    "}\n"71                    "define void @g() {\n"72                    "  unreachable\n"73                    "}\n"74                    "define void @h() {\n"75                    "  unreachable\n"76                    "}\n"77                    "define void @j() {\n"78                    "  unreachable\n"79                    "}\n");80  EXPECT_FALSE(verifyModule(*M, &dbgs()));81 82  Function *F = M->getFunction("f");83  Function *G = M->getFunction("g");84  Function *H = M->getFunction("h");85  Function *J = M->getFunction("j");86 87  // Initially all functions are not materialized (no basic blocks).88  EXPECT_TRUE(F->empty());89  EXPECT_TRUE(G->empty());90  EXPECT_TRUE(H->empty());91  EXPECT_TRUE(J->empty());92  EXPECT_FALSE(verifyModule(*M, &dbgs()));93 94  // Materialize h.95  ASSERT_FALSE(H->materialize());96  EXPECT_TRUE(F->empty());97  EXPECT_TRUE(G->empty());98  EXPECT_FALSE(H->empty());99  EXPECT_TRUE(J->empty());100  EXPECT_FALSE(verifyModule(*M, &dbgs()));101 102  // Materialize g.103  ASSERT_FALSE(G->materialize());104  EXPECT_TRUE(F->empty());105  EXPECT_FALSE(G->empty());106  EXPECT_FALSE(H->empty());107  EXPECT_TRUE(J->empty());108  EXPECT_FALSE(verifyModule(*M, &dbgs()));109 110  // Materialize j.111  ASSERT_FALSE(J->materialize());112  EXPECT_TRUE(F->empty());113  EXPECT_FALSE(G->empty());114  EXPECT_FALSE(H->empty());115  EXPECT_FALSE(J->empty());116  EXPECT_FALSE(verifyModule(*M, &dbgs()));117 118  // Materialize f.119  ASSERT_FALSE(F->materialize());120  EXPECT_FALSE(F->empty());121  EXPECT_FALSE(G->empty());122  EXPECT_FALSE(H->empty());123  EXPECT_FALSE(J->empty());124  EXPECT_FALSE(verifyModule(*M, &dbgs()));125}126 127TEST(BitReaderTest, MaterializeFunctionsStrictFP) {128  SmallString<1024> Mem;129 130  LLVMContext Context;131  std::unique_ptr<Module> M = getLazyModuleFromAssembly(132      Context, Mem, "define double @foo(double %a) {\n"133                    "  %result = call double @bar(double %a) strictfp\n"134                    "  ret double %result\n"135                    "}\n"136                    "declare double @bar(double)\n");137  Function *Foo = M->getFunction("foo");138  ASSERT_FALSE(Foo->materialize());139  EXPECT_FALSE(Foo->empty());140 141  for (auto &BB : *Foo) {142    auto It = BB.begin();143    while (It != BB.end()) {144      Instruction &I = *It;145      ++It;146 147      if (auto *Call = dyn_cast<CallBase>(&I)) {148        EXPECT_FALSE(Call->isStrictFP());149        EXPECT_TRUE(Call->isNoBuiltin());150      }151    }152  }153 154  EXPECT_FALSE(verifyModule(*M, &dbgs()));155}156 157TEST(BitReaderTest, MaterializeConstrainedFPStrictFP) {158  SmallString<1024> Mem;159 160  LLVMContext Context;161  std::unique_ptr<Module> M = getLazyModuleFromAssembly(162      Context, Mem,163      "define double @foo(double %a) strictfp {\n"164      "  %result = call double @llvm.experimental.constrained.sqrt.f64(double "165      "%a, metadata !\"round.tonearest\", metadata !\"fpexcept.strict\") "166      "strictfp\n"167      "  ret double %result\n"168      "}\n"169      "declare double @llvm.experimental.constrained.sqrt.f64(double, "170      "metadata, metadata)\n");171  Function *Foo = M->getFunction("foo");172  ASSERT_FALSE(Foo->materialize());173  EXPECT_FALSE(Foo->empty());174 175  for (auto &BB : *Foo) {176    auto It = BB.begin();177    while (It != BB.end()) {178      Instruction &I = *It;179      ++It;180 181      if (auto *Call = dyn_cast<CallBase>(&I)) {182        EXPECT_TRUE(Call->isStrictFP());183        EXPECT_FALSE(Call->isNoBuiltin());184      }185    }186  }187 188  EXPECT_FALSE(verifyModule(*M, &dbgs()));189}190 191TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677192  SmallString<1024> Mem;193 194  LLVMContext Context;195  std::unique_ptr<Module> M = getLazyModuleFromAssembly(196      Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"197                    "define void @func() {\n"198                    "  unreachable\n"199                    "bb:\n"200                    "  unreachable\n"201                    "}\n");202  EXPECT_FALSE(verifyModule(*M, &dbgs()));203  EXPECT_FALSE(M->getFunction("func")->empty());204}205 206TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {207  SmallString<1024> Mem;208 209  LLVMContext Context;210  std::unique_ptr<Module> M = getLazyModuleFromAssembly(211      Context, Mem, "define i8* @before() {\n"212                    "  ret i8* blockaddress(@func, %bb)\n"213                    "}\n"214                    "define void @other() {\n"215                    "  unreachable\n"216                    "}\n"217                    "define void @func() {\n"218                    "  unreachable\n"219                    "bb:\n"220                    "  unreachable\n"221                    "}\n");222  EXPECT_TRUE(M->getFunction("before")->empty());223  EXPECT_TRUE(M->getFunction("func")->empty());224  EXPECT_FALSE(verifyModule(*M, &dbgs()));225 226  // Materialize @before, pulling in @func.227  EXPECT_FALSE(M->getFunction("before")->materialize());228  EXPECT_FALSE(M->getFunction("func")->empty());229  EXPECT_TRUE(M->getFunction("other")->empty());230  EXPECT_FALSE(verifyModule(*M, &dbgs()));231}232 233TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {234  SmallString<1024> Mem;235 236  LLVMContext Context;237  std::unique_ptr<Module> M = getLazyModuleFromAssembly(238      Context, Mem, "define void @func() {\n"239                    "  unreachable\n"240                    "bb:\n"241                    "  unreachable\n"242                    "}\n"243                    "define void @other() {\n"244                    "  unreachable\n"245                    "}\n"246                    "define i8* @after() {\n"247                    "  ret i8* blockaddress(@func, %bb)\n"248                    "}\n");249  EXPECT_TRUE(M->getFunction("after")->empty());250  EXPECT_TRUE(M->getFunction("func")->empty());251  EXPECT_FALSE(verifyModule(*M, &dbgs()));252 253  // Materialize @after, pulling in @func.254  EXPECT_FALSE(M->getFunction("after")->materialize());255  EXPECT_FALSE(M->getFunction("func")->empty());256  EXPECT_TRUE(M->getFunction("other")->empty());257  EXPECT_FALSE(verifyModule(*M, &dbgs()));258}259 260// Helper function to convert type metadata to a string for testing261static std::string mdToString(Metadata *MD) {262  std::string S;263  if (auto *VMD = dyn_cast<ValueAsMetadata>(MD)) {264    if (VMD->getType()->isPointerTy()) {265      S += "ptr";266      return S;267    }268  }269 270  if (auto *TMD = dyn_cast<MDTuple>(MD)) {271    S += "!{";272    for (unsigned I = 0; I < TMD->getNumOperands(); I++) {273      if (I != 0)274        S += ", ";275      S += mdToString(TMD->getOperand(I).get());276    }277    S += "}";278  } else if (auto *SMD = dyn_cast<MDString>(MD)) {279    S += "!'";280    S += SMD->getString();281    S += "'";282  } else if (auto *I = mdconst::dyn_extract<ConstantInt>(MD)) {283    S += std::to_string(I->getZExtValue());284  } else if (auto *P = mdconst::dyn_extract<PoisonValue>(MD)) {285    auto *Ty = P->getType();286    if (Ty->isIntegerTy()) {287      S += "i";288      S += std::to_string(Ty->getIntegerBitWidth());289    } else if (Ty->isStructTy()) {290      S += "%";291      S += Ty->getStructName();292    } else {293      llvm_unreachable("unhandled poison metadata");294    }295  } else {296    llvm_unreachable("unhandled metadata");297  }298  return S;299}300 301// Recursively look into a (pointer) type and the the type.302// For primitive types it's a poison value of the type, for a pointer it's a303// metadata tuple with the addrspace and the referenced type. For a function,304// it's a tuple where the first element is the string "function", the second305// element is the return type or the string "void" and the following elements306// are the argument types.307static Metadata *getTypeMetadataEntry(unsigned TypeID, LLVMContext &Context,308                                      GetTypeByIDTy GetTypeByID,309                                      GetContainedTypeIDTy GetContainedTypeID) {310  Type *Ty = GetTypeByID(TypeID);311  if (auto *FTy = dyn_cast<FunctionType>(Ty)) {312    // Save the function signature as metadata313    SmallVector<Metadata *> SignatureMD;314    SignatureMD.push_back(MDString::get(Context, "function"));315    // Return type316    if (FTy->getReturnType()->isVoidTy())317      SignatureMD.push_back(MDString::get(Context, "void"));318    else319      SignatureMD.push_back(getTypeMetadataEntry(GetContainedTypeID(TypeID, 0),320                                                 Context, GetTypeByID,321                                                 GetContainedTypeID));322    // Arguments323    for (unsigned I = 0; I != FTy->getNumParams(); ++I)324      SignatureMD.push_back(325          getTypeMetadataEntry(GetContainedTypeID(TypeID, I + 1), Context,326                               GetTypeByID, GetContainedTypeID));327 328    return MDTuple::get(Context, SignatureMD);329  }330 331  if (!Ty->isPointerTy())332    return ConstantAsMetadata::get(PoisonValue::get(Ty));333 334  // Return !{<addrspace>, <inner>} for pointer335  SmallVector<Metadata *, 2> MD;336  MD.push_back(ConstantAsMetadata::get(ConstantInt::get(337      Type::getInt32Ty(Context), Ty->getPointerAddressSpace())));338  MD.push_back(getTypeMetadataEntry(GetContainedTypeID(TypeID, 0), Context,339                                    GetTypeByID, GetContainedTypeID));340  return MDTuple::get(Context, MD);341}342 343// Test that when reading bitcode with typed pointers and upgrading them to344// opaque pointers, the type information of function signatures can be extracted345// and stored in metadata.346TEST(BitReaderTest, AccessFunctionTypeInfo) {347  StringRef Bitcode(reinterpret_cast<const char *>(AccessFunctionTypeInfoBc),348                    sizeof(AccessFunctionTypeInfoBc));349 350  LLVMContext Context;351  ParserCallbacks Callbacks;352  // Supply a callback that stores the signature of a function into metadata,353  // so that the types behind pointers can be accessed.354  // Each function gets a !types metadata, which is a tuple with one element355  // for a non-void return type and every argument. For primitive types it's356  // a poison value of the type, for a pointer it's a metadata tuple with357  // the addrspace and the referenced type.358  Callbacks.ValueType = [&](Value *V, unsigned TypeID,359                            GetTypeByIDTy GetTypeByID,360                            GetContainedTypeIDTy GetContainedTypeID) {361    if (auto *F = dyn_cast<Function>(V)) {362      auto *MD = getTypeMetadataEntry(TypeID, F->getContext(), GetTypeByID,363                                      GetContainedTypeID);364      F->setMetadata("types", cast<MDNode>(MD));365    }366  };367 368  Expected<std::unique_ptr<Module>> ModuleOrErr =369      parseBitcodeFile(MemoryBufferRef(Bitcode, "test"), Context, Callbacks);370 371  if (!ModuleOrErr)372    report_fatal_error("Could not parse bitcode module");373  std::unique_ptr<Module> M = std::move(ModuleOrErr.get());374 375  EXPECT_EQ(mdToString(M->getFunction("func")->getMetadata("types")),376            "!{!'function', !'void'}");377  EXPECT_EQ(mdToString(M->getFunction("func_header")->getMetadata("types")),378            "!{!'function', i32}");379  EXPECT_EQ(mdToString(M->getFunction("ret_ptr")->getMetadata("types")),380            "!{!'function', !{0, i8}}");381  EXPECT_EQ(mdToString(M->getFunction("ret_and_arg_ptr")->getMetadata("types")),382            "!{!'function', !{0, i8}, !{8, i32}}");383  EXPECT_EQ(mdToString(M->getFunction("double_ptr")->getMetadata("types")),384            "!{!'function', !{1, i8}, !{2, !{0, i32}}, !{0, !{0, !{0, i32}}}}");385}386 387// Test that when reading bitcode with typed pointers and upgrading them to388// opaque pointers, the type information of pointers in metadata can be389// extracted and stored in metadata.390TEST(BitReaderTest, AccessMetadataTypeInfo) {391  StringRef Bitcode(reinterpret_cast<const char *>(AccessMetadataTypeInfoBc),392                    sizeof(AccessFunctionTypeInfoBc));393 394  LLVMContext Context;395  ParserCallbacks Callbacks;396  // Supply a callback that stores types from metadata,397  // so that the types behind pointers can be accessed.398  // Non-pointer entries are ignored. Values with a pointer type are399  // replaced by a metadata tuple with {original value, type md}. We cannot400  // save the metadata outside because after conversion to opaque pointers,401  // entries are not distinguishable anymore (e.g. i32* and i8* are both402  // upgraded to ptr).403  Callbacks.MDType = [&](Metadata **Val, unsigned TypeID,404                         GetTypeByIDTy GetTypeByID,405                         GetContainedTypeIDTy GetContainedTypeID) {406    auto *OrigVal = cast<ValueAsMetadata>(*Val);407    if (OrigVal->getType()->isPointerTy()) {408      // Ignore function references, their signature can be saved like409      // in the test above410      if (!isa<Function>(OrigVal->getValue())) {411        SmallVector<Metadata *> Tuple;412        Tuple.push_back(OrigVal);413        Tuple.push_back(getTypeMetadataEntry(GetContainedTypeID(TypeID, 0),414                                             OrigVal->getContext(), GetTypeByID,415                                             GetContainedTypeID));416        *Val = MDTuple::get(OrigVal->getContext(), Tuple);417      }418    }419  };420 421  Expected<std::unique_ptr<Module>> ModuleOrErr =422      parseBitcodeFile(MemoryBufferRef(Bitcode, "test"), Context, Callbacks);423 424  if (!ModuleOrErr)425    report_fatal_error("Could not parse bitcode module");426  std::unique_ptr<Module> M = std::move(ModuleOrErr.get());427 428  EXPECT_EQ(429      mdToString(M->getNamedMetadata("md")->getOperand(0)),430      "!{2, !{ptr, %dx.types.f32}, ptr, !{ptr, !{!'function', !'void'}}}");431  EXPECT_EQ(mdToString(M->getNamedMetadata("md2")->getOperand(0)),432            "!{!{ptr, !{!'function', !{0, i8}, !{2, !{0, i32}}}}, !{ptr, !{0, "433            "!{0, i32}}}}");434}435 436} // end namespace437