brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.7 KiB · 898a829 Raw
538 lines · cpp
1//===- llvm/unittest/AsmParser/AsmParserTest.cpp - asm parser unittests ---===//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 "llvm/ADT/STLExtras.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/AsmParser/AsmParserContext.h"12#include "llvm/AsmParser/Parser.h"13#include "llvm/AsmParser/SlotMapping.h"14#include "llvm/IR/Constants.h"15#include "llvm/IR/DataLayout.h"16#include "llvm/IR/DebugInfoMetadata.h"17#include "llvm/IR/LLVMContext.h"18#include "llvm/IR/Module.h"19#include "llvm/IR/Value.h"20#include "llvm/Support/Debug.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/SourceMgr.h"23#include "gtest/gtest.h"24 25#define DEBUG_TYPE "unittest-asm-parser-tests"26 27using namespace llvm;28 29namespace {30 31TEST(AsmParserTest, NullTerminatedInput) {32  LLVMContext Ctx;33  StringRef Source = "; Empty module \n";34  SMDiagnostic Error;35  auto Mod = parseAssemblyString(Source, Error, Ctx);36 37  EXPECT_TRUE(Mod != nullptr);38  EXPECT_TRUE(Error.getMessage().empty());39}40 41#ifdef GTEST_HAS_DEATH_TEST42#ifndef NDEBUG43 44TEST(AsmParserTest, NonNullTerminatedInput) {45  LLVMContext Ctx;46  StringRef Source = "; Empty module \n\1\2";47  SMDiagnostic Error;48  std::unique_ptr<Module> Mod;49  EXPECT_DEATH(Mod = parseAssemblyString(Source.substr(0, Source.size() - 2),50                                         Error, Ctx),51               "Buffer is not null terminated!");52}53 54#endif55#endif56 57TEST(AsmParserTest, SlotMappingTest) {58  LLVMContext Ctx;59  StringRef Source = "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}";60  SMDiagnostic Error;61  SlotMapping Mapping;62  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);63 64  EXPECT_TRUE(Mod != nullptr);65  EXPECT_TRUE(Error.getMessage().empty());66 67  ASSERT_EQ(Mapping.GlobalValues.getNext(), 1u);68  EXPECT_TRUE(isa<GlobalVariable>(Mapping.GlobalValues.get(0)));69 70  EXPECT_EQ(Mapping.MetadataNodes.size(), 2u);71  EXPECT_EQ(Mapping.MetadataNodes.count(0), 1u);72  EXPECT_EQ(Mapping.MetadataNodes.count(42), 1u);73  EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u);74}75 76TEST(AsmParserTest, TypeAndConstantValueParsing) {77  LLVMContext Ctx;78  SMDiagnostic Error;79  StringRef Source = "define void @test() {\n  entry:\n  ret void\n}";80  auto Mod = parseAssemblyString(Source, Error, Ctx);81  ASSERT_TRUE(Mod != nullptr);82  auto &M = *Mod;83 84  const Value *V;85  V = parseConstantValue("double 3.5", Error, M);86  ASSERT_TRUE(V);87  EXPECT_TRUE(V->getType()->isDoubleTy());88  ASSERT_TRUE(isa<ConstantFP>(V));89  EXPECT_TRUE(cast<ConstantFP>(V)->isExactlyValue(3.5));90 91  V = parseConstantValue("i32 42", Error, M);92  ASSERT_TRUE(V);93  EXPECT_TRUE(V->getType()->isIntegerTy());94  ASSERT_TRUE(isa<ConstantInt>(V));95  EXPECT_TRUE(cast<ConstantInt>(V)->equalsInt(42));96 97  V = parseConstantValue("<4 x i32> <i32 0, i32 1, i32 2, i32 3>", Error, M);98  ASSERT_TRUE(V);99  EXPECT_TRUE(V->getType()->isVectorTy());100  ASSERT_TRUE(isa<ConstantDataVector>(V));101 102  V = parseConstantValue("<4 x i32> splat (i32 -2)", Error, M);103  ASSERT_TRUE(V);104  EXPECT_TRUE(V->getType()->isVectorTy());105  ASSERT_TRUE(isa<ConstantDataVector>(V));106 107  V = parseConstantValue("<4 x i32> zeroinitializer", Error, M);108  ASSERT_TRUE(V);109  EXPECT_TRUE(V->getType()->isVectorTy());110  ASSERT_TRUE(isa<Constant>(V));111  EXPECT_TRUE(cast<Constant>(V)->isNullValue());112 113  V = parseConstantValue("<4 x i32> poison", Error, M);114  ASSERT_TRUE(V);115  EXPECT_TRUE(V->getType()->isVectorTy());116  ASSERT_TRUE(isa<PoisonValue>(V));117 118  V = parseConstantValue("i32 add (i32 1, i32 2)", Error, M);119  ASSERT_TRUE(V);120  ASSERT_TRUE(isa<ConstantInt>(V));121 122  V = parseConstantValue("ptr blockaddress(@test, %entry)", Error, M);123  ASSERT_TRUE(V);124  ASSERT_TRUE(isa<BlockAddress>(V));125 126  V = parseConstantValue("ptr undef", Error, M);127  ASSERT_TRUE(V);128  ASSERT_TRUE(isa<UndefValue>(V));129 130  V = parseConstantValue("ptr poison", Error, M);131  ASSERT_TRUE(V);132  ASSERT_TRUE(isa<PoisonValue>(V));133 134  EXPECT_FALSE(parseConstantValue("duble 3.25", Error, M));135  EXPECT_EQ(Error.getMessage(), "expected type");136 137  EXPECT_FALSE(parseConstantValue("i32 3.25", Error, M));138  EXPECT_EQ(Error.getMessage(), "floating point constant invalid for type");139 140  EXPECT_FALSE(parseConstantValue("ptr @foo", Error, M));141  EXPECT_EQ(Error.getMessage(), "expected a constant value");142 143  EXPECT_FALSE(parseConstantValue("i32 3, ", Error, M));144  EXPECT_EQ(Error.getMessage(), "expected end of string");145}146 147TEST(AsmParserTest, TypeAndConstantValueWithSlotMappingParsing) {148  LLVMContext Ctx;149  SMDiagnostic Error;150  StringRef Source =151      "%st = type { i32, i32 }\n"152      "@v = common global [50 x %st] zeroinitializer, align 16\n"153      "%0 = type { i32, i32, i32, i32 }\n"154      "@g = common global [50 x %0] zeroinitializer, align 16\n"155      "define void @marker4(i64 %d) {\n"156      "entry:\n"157      "  %conv = trunc i64 %d to i32\n"158      "  store i32 %conv, ptr getelementptr inbounds "159      "    ([50 x %st], ptr @v, i64 0, i64 1, i32 0), align 16\n"160      "  store i32 %conv, ptr getelementptr inbounds "161      "    ([50 x %0], ptr @g, i64 0, i64 1, i32 0), align 16\n"162      "  ret void\n"163      "}";164  SlotMapping Mapping;165  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);166  ASSERT_TRUE(Mod != nullptr);167  auto &M = *Mod;168 169  const Value *V;170  V = parseConstantValue("ptr getelementptr inbounds ([50 x %st], ptr "171                         "@v, i64 0, i64 1, i32 0)",172                         Error, M, &Mapping);173  ASSERT_TRUE(V);174  ASSERT_TRUE(isa<ConstantExpr>(V));175 176  V = parseConstantValue("ptr getelementptr inbounds ([50 x %0], ptr "177                         "@g, i64 0, i64 1, i32 0)",178                         Error, M, &Mapping);179  ASSERT_TRUE(V);180  ASSERT_TRUE(isa<ConstantExpr>(V));181}182 183TEST(AsmParserTest, TypeWithSlotMappingParsing) {184  LLVMContext Ctx;185  SMDiagnostic Error;186  StringRef Source =187      "%st = type { i32, i32 }\n"188      "@v = common global [50 x %st] zeroinitializer, align 16\n"189      "%0 = type { i32, i32, i32, i32 }\n"190      "@g = common global [50 x %0] zeroinitializer, align 16\n"191      "define void @marker4(i64 %d) {\n"192      "entry:\n"193      "  %conv = trunc i64 %d to i32\n"194      "  store i32 %conv, ptr getelementptr inbounds "195      "    ([50 x %st], ptr @v, i64 0, i64 0, i32 0), align 16\n"196      "  store i32 %conv, ptr getelementptr inbounds "197      "    ([50 x %0], ptr @g, i64 0, i64 0, i32 0), align 16\n"198      "  ret void\n"199      "}";200  SlotMapping Mapping;201  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);202  ASSERT_TRUE(Mod != nullptr);203  auto &M = *Mod;204 205  // Check we properly parse integer types.206  Type *Ty;207  Ty = parseType("i32", Error, M, &Mapping);208  ASSERT_TRUE(Ty);209  ASSERT_TRUE(Ty->isIntegerTy());210  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);211 212  // Check we properly parse integer types with exotic size.213  Ty = parseType("i13", Error, M, &Mapping);214  ASSERT_TRUE(Ty);215  ASSERT_TRUE(Ty->isIntegerTy());216  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13);217 218  // Check we properly parse floating point types.219  Ty = parseType("float", Error, M, &Mapping);220  ASSERT_TRUE(Ty);221  ASSERT_TRUE(Ty->isFloatTy());222 223  Ty = parseType("double", Error, M, &Mapping);224  ASSERT_TRUE(Ty);225  ASSERT_TRUE(Ty->isDoubleTy());226 227  // Check we properly parse struct types.228  // Named struct.229  Ty = parseType("%st", Error, M, &Mapping);230  ASSERT_TRUE(Ty);231  ASSERT_TRUE(Ty->isStructTy());232 233  // Check the details of the struct.234  StructType *ST = cast<StructType>(Ty);235  ASSERT_TRUE(ST->getNumElements() == 2);236  for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {237    Ty = ST->getElementType(i);238    ASSERT_TRUE(Ty->isIntegerTy());239    ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);240  }241 242  // Anonymous struct.243  Ty = parseType("%0", Error, M, &Mapping);244  ASSERT_TRUE(Ty);245  ASSERT_TRUE(Ty->isStructTy());246 247  // Check the details of the struct.248  ST = cast<StructType>(Ty);249  ASSERT_TRUE(ST->getNumElements() == 4);250  for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {251    Ty = ST->getElementType(i);252    ASSERT_TRUE(Ty->isIntegerTy());253    ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);254  }255 256  // Check we properly parse vector types.257  Ty = parseType("<5 x i32>", Error, M, &Mapping);258  ASSERT_TRUE(Ty);259  ASSERT_TRUE(Ty->isVectorTy());260 261  // Check the details of the vector.262  auto *VT = cast<FixedVectorType>(Ty);263  ASSERT_TRUE(VT->getNumElements() == 5);264  ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedValue() == 160);265  Ty = VT->getElementType();266  ASSERT_TRUE(Ty->isIntegerTy());267  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);268 269  // Opaque struct.270  Ty = parseType("%opaque", Error, M, &Mapping);271  ASSERT_TRUE(Ty);272  ASSERT_TRUE(Ty->isStructTy());273 274  ST = cast<StructType>(Ty);275  ASSERT_TRUE(ST->isOpaque());276 277  // Check we properly parse pointer types.278  Ty = parseType("ptr", Error, M, &Mapping);279  ASSERT_TRUE(Ty);280  ASSERT_TRUE(Ty->isPointerTy());281 282  // Check that we reject types with garbage.283  Ty = parseType("i32 garbage", Error, M, &Mapping);284  ASSERT_TRUE(!Ty);285}286 287TEST(AsmParserTest, TypeAtBeginningWithSlotMappingParsing) {288  LLVMContext Ctx;289  SMDiagnostic Error;290  StringRef Source =291      "%st = type { i32, i32 }\n"292      "@v = common global [50 x %st] zeroinitializer, align 16\n"293      "%0 = type { i32, i32, i32, i32 }\n"294      "@g = common global [50 x %0] zeroinitializer, align 16\n"295      "define void @marker4(i64 %d) {\n"296      "entry:\n"297      "  %conv = trunc i64 %d to i32\n"298      "  store i32 %conv, ptr getelementptr inbounds "299      "    ([50 x %st], ptr @v, i64 0, i64 0, i32 0), align 16\n"300      "  store i32 %conv, ptr getelementptr inbounds "301      "    ([50 x %0], ptr @g, i64 0, i64 0, i32 0), align 16\n"302      "  ret void\n"303      "}";304  SlotMapping Mapping;305  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);306  ASSERT_TRUE(Mod != nullptr);307  auto &M = *Mod;308  unsigned Read;309 310  // Check we properly parse integer types.311  Type *Ty;312  Ty = parseTypeAtBeginning("i32", Read, Error, M, &Mapping);313  ASSERT_TRUE(Ty);314  ASSERT_TRUE(Ty->isIntegerTy());315  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);316  ASSERT_TRUE(Read == 3);317 318  // Check we properly parse integer types with exotic size.319  Ty = parseTypeAtBeginning("i13", Read, Error, M, &Mapping);320  ASSERT_TRUE(Ty);321  ASSERT_TRUE(Ty->isIntegerTy());322  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13);323  ASSERT_TRUE(Read == 3);324 325  // Check we properly parse floating point types.326  Ty = parseTypeAtBeginning("float", Read, Error, M, &Mapping);327  ASSERT_TRUE(Ty);328  ASSERT_TRUE(Ty->isFloatTy());329  ASSERT_TRUE(Read == 5);330 331  Ty = parseTypeAtBeginning("double", Read, Error, M, &Mapping);332  ASSERT_TRUE(Ty);333  ASSERT_TRUE(Ty->isDoubleTy());334  ASSERT_TRUE(Read == 6);335 336  // Check we properly parse struct types.337  // Named struct.338  Ty = parseTypeAtBeginning("%st", Read, Error, M, &Mapping);339  ASSERT_TRUE(Ty);340  ASSERT_TRUE(Ty->isStructTy());341  ASSERT_TRUE(Read == 3);342 343  // Check the details of the struct.344  StructType *ST = cast<StructType>(Ty);345  ASSERT_TRUE(ST->getNumElements() == 2);346  for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {347    Ty = ST->getElementType(i);348    ASSERT_TRUE(Ty->isIntegerTy());349    ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);350  }351 352  // Anonymous struct.353  Ty = parseTypeAtBeginning("%0", Read, Error, M, &Mapping);354  ASSERT_TRUE(Ty);355  ASSERT_TRUE(Ty->isStructTy());356  ASSERT_TRUE(Read == 2);357 358  // Check the details of the struct.359  ST = cast<StructType>(Ty);360  ASSERT_TRUE(ST->getNumElements() == 4);361  for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {362    Ty = ST->getElementType(i);363    ASSERT_TRUE(Ty->isIntegerTy());364    ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);365  }366 367  // Check we properly parse vector types.368  Ty = parseTypeAtBeginning("<5 x i32>", Read, Error, M, &Mapping);369  ASSERT_TRUE(Ty);370  ASSERT_TRUE(Ty->isVectorTy());371  ASSERT_TRUE(Read == 9);372 373  // Check the details of the vector.374  auto *VT = cast<FixedVectorType>(Ty);375  ASSERT_TRUE(VT->getNumElements() == 5);376  ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedValue() == 160);377  Ty = VT->getElementType();378  ASSERT_TRUE(Ty->isIntegerTy());379  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);380 381  // Opaque struct.382  Ty = parseTypeAtBeginning("%opaque", Read, Error, M, &Mapping);383  ASSERT_TRUE(Ty);384  ASSERT_TRUE(Ty->isStructTy());385  ASSERT_TRUE(Read == 7);386 387  ST = cast<StructType>(Ty);388  ASSERT_TRUE(ST->isOpaque());389 390  // Check we properly parse pointer types.391  // One indirection.392  Ty = parseTypeAtBeginning("ptr", Read, Error, M, &Mapping);393  ASSERT_TRUE(Ty);394  ASSERT_TRUE(Ty->isPointerTy());395  ASSERT_TRUE(Read == 3);396 397  // Check that we reject types with garbage.398  Ty = parseTypeAtBeginning("i32 garbage", Read, Error, M, &Mapping);399  ASSERT_TRUE(Ty);400  ASSERT_TRUE(Ty->isIntegerTy());401  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);402  // We go to the next token, i.e., we read "i32" + ' '.403  ASSERT_TRUE(Read == 4);404}405 406TEST(AsmParserTest, InvalidDataLayoutStringCallback) {407  LLVMContext Ctx;408  SMDiagnostic Error;409  // Note the invalid i8:7 part410  // Overalign i32 as marker so we can check that indeed this DL was used,411  // and not some default.412  StringRef InvalidDLStr =413      "e-m:e-p:64:64-i8:7-i16:16-i32:64-i64:64-f80:128-n8:16:32:64";414  StringRef FixedDLStr =415      "e-m:e-p:64:64-i8:8-i16:16-i32:64-i64:64-f80:128-n8:16:32:64";416  Expected<DataLayout> ExpectedFixedDL = DataLayout::parse(FixedDLStr);417  ASSERT_TRUE(!ExpectedFixedDL.takeError());418  DataLayout FixedDL = ExpectedFixedDL.get();419  std::string Source = ("target datalayout = \"" + InvalidDLStr + "\"\n").str();420  MemoryBufferRef SourceBuffer(Source, "<string>");421 422  // Check that we reject the source without a DL override.423  SlotMapping Mapping1;424  auto Mod1 = parseAssembly(SourceBuffer, Error, Ctx, &Mapping1);425  EXPECT_TRUE(Mod1 == nullptr);426 427  // Check that we pass the correct DL str to the callback,428  // that fixing the DL str from the callback works,429  // and that the resulting module has the correct DL.430  SlotMapping Mapping2;431  auto Mod2 = parseAssembly(432      SourceBuffer, Error, Ctx, &Mapping2,433      [&](StringRef Triple, StringRef DLStr) -> std::optional<std::string> {434        EXPECT_EQ(DLStr, InvalidDLStr);435        return std::string{FixedDLStr};436      });437  ASSERT_TRUE(Mod2 != nullptr);438  EXPECT_EQ(Mod2->getDataLayout(), FixedDL);439}440 441TEST(AsmParserTest, DIExpressionBodyAtBeginningWithSlotMappingParsing) {442  LLVMContext Ctx;443  SMDiagnostic Error;444  StringRef Source = "";445  SlotMapping Mapping;446  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);447  ASSERT_TRUE(Mod != nullptr);448  auto &M = *Mod;449  unsigned Read;450 451  ASSERT_EQ(Mapping.MetadataNodes.size(), 0u);452 453  DIExpression *Expr;454 455  Expr = parseDIExpressionBodyAtBeginning("()", Read, Error, M, &Mapping);456  ASSERT_TRUE(Expr);457  ASSERT_EQ(Expr->getNumElements(), 0u);458 459  Expr = parseDIExpressionBodyAtBeginning("(0)", Read, Error, M, &Mapping);460  ASSERT_TRUE(Expr);461  ASSERT_EQ(Expr->getNumElements(), 1u);462 463  Expr = parseDIExpressionBodyAtBeginning("(DW_OP_LLVM_fragment, 0, 1)", Read,464                                          Error, M, &Mapping);465  ASSERT_TRUE(Expr);466  ASSERT_EQ(Expr->getNumElements(), 3u);467 468  Expr = parseDIExpressionBodyAtBeginning(469      "(DW_OP_LLVM_fragment, 0, 1)  trailing source", Read, Error, M, &Mapping);470  ASSERT_TRUE(Expr);471  ASSERT_EQ(Expr->getNumElements(), 3u);472  ASSERT_EQ(Read, StringRef("(DW_OP_LLVM_fragment, 0, 1)  ").size());473 474  Error = {};475  Expr = parseDIExpressionBodyAtBeginning("i32", Read, Error, M, &Mapping);476  ASSERT_FALSE(Expr);477  ASSERT_EQ(Error.getMessage(), "expected '(' here");478 479  Error = {};480  Expr = parseDIExpressionBodyAtBeginning(481      "!DIExpression(DW_OP_LLVM_fragment, 0, 1)", Read, Error, M, &Mapping);482  ASSERT_FALSE(Expr);483  ASSERT_EQ(Error.getMessage(), "expected '(' here");484 485  ASSERT_EQ(Mapping.MetadataNodes.size(), 0u);486}487 488#define ASSERT_EQ_LOC(Loc1, Loc2)                                              \489  do {                                                                         \490    EXPECT_TRUE(Loc1.contains(Loc2) && Loc2.contains(Loc1))                    \491        << #Loc1 " location: " << Loc1.Start.Line << ":" << Loc1.Start.Col     \492        << " - " << Loc1.End.Line << ":" << Loc1.End.Col << "\n"               \493        << #Loc2 " location: " << Loc2.Start.Line << ":" << Loc2.Start.Col     \494        << " - " << Loc2.End.Line << ":" << Loc2.End.Col << "\n";              \495  } while (false)496 497TEST(AsmParserTest, ParserObjectLocations) {498  StringRef Source = "define i32 @main() {\n"499                     "entry:\n"500                     "    %a = add i32 1, 2\n"501                     "    ret i32 %a\n"502                     "}\n";503  LLVMContext Ctx;504  SMDiagnostic Error;505  SlotMapping Mapping;506  AsmParserContext ParserContext;507  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping, &ParserContext);508 509  auto *MainFn = Mod->getFunction("main");510  ASSERT_TRUE(MainFn != nullptr);511 512  auto MaybeMainLoc = ParserContext.getFunctionLocation(MainFn);513  EXPECT_TRUE(MaybeMainLoc.has_value());514  auto MainLoc = MaybeMainLoc.value();515  auto ExpectedMainLoc = FileLocRange(FileLoc{0, 0}, FileLoc{4, 1});516  ASSERT_EQ_LOC(MainLoc, ExpectedMainLoc);517 518  auto &EntryBB = MainFn->getEntryBlock();519  auto MaybeEntryBBLoc = ParserContext.getBlockLocation(&EntryBB);520  ASSERT_TRUE(MaybeEntryBBLoc.has_value());521  auto EntryBBLoc = MaybeEntryBBLoc.value();522  auto ExpectedEntryBBLoc = FileLocRange(FileLoc{1, 0}, FileLoc{3, 14});523  ASSERT_EQ_LOC(EntryBBLoc, ExpectedEntryBBLoc);524 525  SmallVector<FileLocRange> InstructionLocations = {526      FileLocRange(FileLoc{2, 4}, FileLoc{2, 21}),527      FileLocRange(FileLoc{3, 4}, FileLoc{3, 14})};528 529  for (const auto &[Inst, ExpectedLoc] : zip(EntryBB, InstructionLocations)) {530    auto MaybeInstLoc = ParserContext.getInstructionLocation(&Inst);531    ASSERT_TRUE(MaybeMainLoc.has_value());532    auto InstLoc = MaybeInstLoc.value();533    ASSERT_EQ_LOC(InstLoc, ExpectedLoc);534  }535}536 537} // end anonymous namespace538