1 //===--- unittests/CodeGen/TestAsmPrinter.cpp -------------------*- C++ -*-===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "TestAsmPrinter.h" 10 #include "llvm/ADT/Triple.h" 11 #include "llvm/CodeGen/AsmPrinter.h" 12 #include "llvm/MC/MCAsmInfo.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/TargetRegistry.h" 15 #include "llvm/Target/TargetLoweringObjectFile.h" 16 #include "llvm/Target/TargetMachine.h" 17 18 using namespace llvm; 19 using ::testing::StrictMock; 20 21 // Note: a non-const reference argument cannot be passed through 22 // testing::StrictMock, thus, we pass a pointer and dereference it here. 23 MockMCStreamer::MockMCStreamer(MCContext *Ctx) : MCStreamer(*Ctx) {} 24 25 MockMCStreamer::~MockMCStreamer() = default; 26 27 TestAsmPrinter::TestAsmPrinter() = default; 28 29 TestAsmPrinter::~TestAsmPrinter() = default; 30 31 llvm::Expected<std::unique_ptr<TestAsmPrinter>> 32 TestAsmPrinter::create(const std::string &TripleStr, uint16_t DwarfVersion, 33 dwarf::DwarfFormat DwarfFormat) { 34 std::string ErrorStr; 35 const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrorStr); 36 if (!TheTarget) 37 return std::unique_ptr<TestAsmPrinter>(); 38 39 std::unique_ptr<TestAsmPrinter> TestPrinter(new TestAsmPrinter); 40 if (llvm::Error E = 41 TestPrinter->init(TheTarget, TripleStr, DwarfVersion, DwarfFormat)) 42 return std::move(E); 43 44 return std::move(TestPrinter); 45 } 46 47 // Note:: based on dwarfgen::Generator::init() from 48 // llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp 49 llvm::Error TestAsmPrinter::init(const Target *TheTarget, StringRef TripleName, 50 uint16_t DwarfVersion, 51 dwarf::DwarfFormat DwarfFormat) { 52 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(), 53 None)); 54 if (!TM) 55 return make_error<StringError>("no target machine for target " + TripleName, 56 inconvertibleErrorCode()); 57 58 Triple TheTriple(TripleName); 59 MC.reset(new MCContext(TheTriple, TM->getMCAsmInfo(), TM->getMCRegisterInfo(), 60 TM->getMCSubtargetInfo())); 61 TM->getObjFileLowering()->Initialize(*MC, *TM); 62 MC->setObjectFileInfo(TM->getObjFileLowering()); 63 64 MS = new StrictMock<MockMCStreamer>(MC.get()); 65 66 Asm.reset( 67 TheTarget->createAsmPrinter(*TM, std::unique_ptr<MockMCStreamer>(MS))); 68 if (!Asm) 69 return make_error<StringError>("no asm printer for target " + TripleName, 70 inconvertibleErrorCode()); 71 72 // Set the DWARF version correctly on all classes that we use. 73 MC->setDwarfVersion(DwarfVersion); 74 Asm->setDwarfVersion(DwarfVersion); 75 76 // Set the DWARF format. 77 MC->setDwarfFormat(DwarfFormat); 78 79 return Error::success(); 80 } 81 82 void TestAsmPrinter::setDwarfUsesRelocationsAcrossSections(bool Enable) { 83 struct HackMCAsmInfo : MCAsmInfo { 84 void setDwarfUsesRelocationsAcrossSections(bool Enable) { 85 DwarfUsesRelocationsAcrossSections = Enable; 86 } 87 }; 88 static_cast<HackMCAsmInfo *>(const_cast<MCAsmInfo *>(TM->getMCAsmInfo())) 89 ->setDwarfUsesRelocationsAcrossSections(Enable); 90 } 91