RuntimeDyld.cpp revision 234353
1105196Swollman//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ----*- C++ -*-===// 22742Swollman// 386464Swollman// The LLVM Compiler Infrastructure 42742Swollman// 52742Swollman// This file is distributed under the University of Illinois Open Source 62742Swollman// License. See LICENSE.TXT for details. 72742Swollman// 82742Swollman//===----------------------------------------------------------------------===// 92742Swollman// 1086222Swollman// Implementation of the MC-JIT runtime dynamic linker. 1186222Swollman// 122742Swollman//===----------------------------------------------------------------------===// 1358787Sru 142742Swollman#define DEBUG_TYPE "dyld" 152742Swollman#include "RuntimeDyldImpl.h" 162742Swollman#include "RuntimeDyldELF.h" 172742Swollman#include "RuntimeDyldMachO.h" 182742Swollman#include "llvm/Support/Path.h" 192742Swollman 2058787Sruusing namespace llvm; 2158787Sruusing namespace llvm::object; 2258787Sru 232742Swollman// Empty out-of-line virtual destructor as the key function. 242742SwollmanRTDyldMemoryManager::~RTDyldMemoryManager() {} 259908SwollmanRuntimeDyldImpl::~RuntimeDyldImpl() {} 262742Swollman 2730711Swollmannamespace llvm { 282742Swollman 299908Swollmannamespace { 302742Swollman // Helper for extensive error checking in debug builds. 3158787Sru error_code Check(error_code Err) { 3258787Sru if (Err) { 3314343Swollman report_fatal_error(Err.message()); 3414343Swollman } 3514343Swollman return Err; 3614343Swollman } 3714343Swollman} // end anonymous namespace 382742Swollman 399908Swollman// Resolve the relocations for all symbols we currently know about. 4020094Swollmanvoid RuntimeDyldImpl::resolveRelocations() { 4120094Swollman // First, resolve relocations associated with external symbols. 4220094Swollman resolveSymbols(); 4320094Swollman 4420094Swollman // Just iterate over the sections we have and resolve all the relocations 4520094Swollman // in them. Gross overkill, but it gets the job done. 4620094Swollman for (int i = 0, e = Sections.size(); i != e; ++i) { 4720094Swollman reassignSectionAddress(i, Sections[i].LoadAddress); 4820094Swollman } 4920094Swollman} 5020094Swollman 5120094Swollmanvoid RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, 5220094Swollman uint64_t TargetAddress) { 5358787Sru for (unsigned i = 0, e = Sections.size(); i != e; ++i) { 5458787Sru if (Sections[i].Address == LocalAddress) { 5521217Swollman reassignSectionAddress(i, TargetAddress); 5621217Swollman return; 5758787Sru } 5858787Sru } 592742Swollman llvm_unreachable("Attempting to remap address of unknown section!"); 6058787Sru} 6121217Swollman 6220094Swollmanbool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { 6358787Sru // FIXME: ObjectFile don't modify MemoryBuffer. 6458787Sru // It should use const MemoryBuffer as parameter. 6520094Swollman OwningPtr<ObjectFile> obj(ObjectFile::createObjectFile( 662742Swollman const_cast<MemoryBuffer*>(InputBuffer))); 679908Swollman if (!obj) 682742Swollman report_fatal_error("Unable to create object image from memory buffer!"); 6914343Swollman 7014343Swollman Arch = (Triple::ArchType)obj->getArch(); 7114343Swollman 7214343Swollman LocalSymbolMap LocalSymbols; // Functions and data symbols from the 7314343Swollman // object file. 7414343Swollman ObjSectionToIDMap LocalSections; // Used sections from the object file 7564499Swollman CommonSymbolMap CommonSymbols; // Common symbols requiring allocation 7664499Swollman uint64_t CommonSize = 0; 7764499Swollman 7864499Swollman error_code err; 7964499Swollman // Parse symbols 8014343Swollman DEBUG(dbgs() << "Parse symbols:\n"); 812742Swollman for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); 822742Swollman i != e; i.increment(err)) { 832742Swollman Check(err); 8458787Sru object::SymbolRef::Type SymType; 852742Swollman StringRef Name; 862742Swollman Check(i->getType(SymType)); 879908Swollman Check(i->getName(Name)); 882742Swollman 8958787Sru uint32_t flags; 9058787Sru Check(i->getFlags(flags)); 9114343Swollman 9214343Swollman bool isCommon = flags & SymbolRef::SF_Common; 9358787Sru if (isCommon) { 9414343Swollman // Add the common symbols to a list. We'll allocate them all below. 9514343Swollman uint64_t Size = 0; 9614343Swollman Check(i->getSize(Size)); 9758787Sru CommonSize += Size; 9814343Swollman CommonSymbols[*i] = Size; 9958787Sru } else { 10058787Sru if (SymType == object::SymbolRef::ST_Function || 10158787Sru SymType == object::SymbolRef::ST_Data) { 10214343Swollman uint64_t FileOffset; 10358787Sru StringRef sData; 10458787Sru section_iterator si = obj->end_sections(); 1052742Swollman Check(i->getFileOffset(FileOffset)); 1062742Swollman Check(i->getSection(si)); 10758787Sru if (si == obj->end_sections()) continue; 10858787Sru Check(si->getContents(sData)); 10958787Sru const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + 1102742Swollman (uintptr_t)FileOffset; 1112742Swollman uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin()); 1129908Swollman unsigned SectionID = 1132742Swollman findOrEmitSection(*si, 11414343Swollman SymType == object::SymbolRef::ST_Function, 11558787Sru LocalSections); 11614343Swollman bool isGlobal = flags & SymbolRef::SF_Global; 11714343Swollman LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); 11858787Sru DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) 11958787Sru << " flags: " << flags 12014343Swollman << " SID: " << SectionID 12114343Swollman << " Offset: " << format("%p", SectOffset)); 12258787Sru if (isGlobal) 12343543Swollman SymbolTable[Name] = SymbolLoc(SectionID, SectOffset); 1242742Swollman } 1252742Swollman } 12658787Sru DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); 1272742Swollman } 1282742Swollman 1299908Swollman // Allocate common symbols 1302742Swollman if (CommonSize != 0) 13114343Swollman emitCommonSymbols(CommonSymbols, CommonSize, LocalSymbols); 13214343Swollman 13314343Swollman // Parse and proccess relocations 13414343Swollman DEBUG(dbgs() << "Parse relocations:\n"); 13514343Swollman for (section_iterator si = obj->begin_sections(), 13614343Swollman se = obj->end_sections(); si != se; si.increment(err)) { 13714343Swollman Check(err); 13843543Swollman bool isFirstRelocation = true; 13914343Swollman unsigned SectionID = 0; 14014343Swollman StubMap Stubs; 14158787Sru 14243543Swollman for (relocation_iterator i = si->begin_relocations(), 1432742Swollman e = si->end_relocations(); i != e; i.increment(err)) { 1442742Swollman Check(err); 14558787Sru 1462742Swollman // If it's first relocation in this section, find its SectionID 1472742Swollman if (isFirstRelocation) { 1482742Swollman SectionID = findOrEmitSection(*si, true, LocalSections); 1492742Swollman DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); 15058787Sru isFirstRelocation = false; 15158787Sru } 15258787Sru 1538029Swollman ObjRelocationInfo RI; 15414343Swollman RI.SectionID = SectionID; 15514343Swollman Check(i->getAdditionalInfo(RI.AdditionalInfo)); 15675267Swollman Check(i->getOffset(RI.Offset)); 15775267Swollman Check(i->getSymbol(RI.Symbol)); 15875267Swollman Check(i->getType(RI.Type)); 15975267Swollman 16075267Swollman DEBUG(dbgs() << "\t\tAddend: " << RI.AdditionalInfo 16175267Swollman << " Offset: " << format("%p", (uintptr_t)RI.Offset) 16275267Swollman << " Type: " << (uint32_t)(RI.Type & 0xffffffffL) 16375267Swollman << "\n"); 16475267Swollman processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs); 16575267Swollman } 1662742Swollman } 1672742Swollman return false; 16814343Swollman} 1698029Swollman 17014343Swollmanunsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map, 1712742Swollman uint64_t TotalSize, 1722742Swollman LocalSymbolMap &LocalSymbols) { 17314343Swollman // Allocate memory for the section 17458787Sru unsigned SectionID = Sections.size(); 1752742Swollman uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*), 17614343Swollman SectionID); 17714343Swollman if (!Addr) 17814343Swollman report_fatal_error("Unable to allocate memory for common symbols!"); 17914343Swollman uint64_t Offset = 0; 18030711Swollman Sections.push_back(SectionEntry(Addr, TotalSize, TotalSize, 0)); 18130711Swollman memset(Addr, 0, TotalSize); 18258787Sru 18358787Sru DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID 1842742Swollman << " new addr: " << format("%p", Addr) 18543014Swollman << " DataSize: " << TotalSize 18643014Swollman << "\n"); 18743014Swollman 18843014Swollman // Assign the address of each symbol 1892742Swollman for (CommonSymbolMap::const_iterator it = Map.begin(), itEnd = Map.end(); 1902742Swollman it != itEnd; it++) { 19158787Sru uint64_t Size = it->second; 1922742Swollman StringRef Name; 19319878Swollman it->first.getName(Name); 19443014Swollman LocalSymbols[Name.data()] = SymbolLoc(SectionID, Offset); 19543014Swollman Offset += Size; 1962742Swollman Addr += Size; 1972742Swollman } 19819878Swollman 19919878Swollman return SectionID; 2002742Swollman} 2012742Swollman 2022742Swollmanunsigned RuntimeDyldImpl::emitSection(const SectionRef &Section, 2032742Swollman bool IsCode) { 20419878Swollman 2052742Swollman unsigned StubBufSize = 0, 2062742Swollman StubSize = getMaxStubSize(); 20743543Swollman error_code err; 20875267Swollman if (StubSize > 0) { 20975267Swollman for (relocation_iterator i = Section.begin_relocations(), 2102742Swollman e = Section.end_relocations(); i != e; i.increment(err), Check(err)) 2112742Swollman StubBufSize += StubSize; 21243543Swollman } 2132742Swollman StringRef data; 2142742Swollman uint64_t Alignment64; 2152742Swollman Check(Section.getContents(data)); 2162742Swollman Check(Section.getAlignment(Alignment64)); 21719878Swollman 2182742Swollman unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; 21919878Swollman bool IsRequired; 2202742Swollman bool IsVirtual; 22119878Swollman bool IsZeroInit; 22243014Swollman uint64_t DataSize; 22343014Swollman Check(Section.isRequiredForExecution(IsRequired)); 2242742Swollman Check(Section.isVirtual(IsVirtual)); 2252742Swollman Check(Section.isZeroInit(IsZeroInit)); 2262742Swollman Check(Section.getSize(DataSize)); 22775267Swollman 22875267Swollman unsigned Allocate; 22975267Swollman unsigned SectionID = Sections.size(); 23075267Swollman uint8_t *Addr; 2312742Swollman const char *pData = 0; 2322742Swollman 2332742Swollman // Some sections, such as debug info, don't need to be loaded for execution. 2342742Swollman // Leave those where they are. 23519878Swollman if (IsRequired) { 2362742Swollman Allocate = DataSize + StubBufSize; 23719878Swollman Addr = IsCode 23819878Swollman ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) 23919878Swollman : MemMgr->allocateDataSection(Allocate, Alignment, SectionID); 2402742Swollman if (!Addr) 24119878Swollman report_fatal_error("Unable to allocate section memory!"); 24219878Swollman 24319878Swollman // Virtual sections have no data in the object image, so leave pData = 0 2442742Swollman if (!IsVirtual) 24514343Swollman pData = data.data(); 24614343Swollman 24775267Swollman // Zero-initialize or copy the data from the image 24875267Swollman if (IsZeroInit || IsVirtual) 24919878Swollman memset(Addr, 0, DataSize); 25075267Swollman else 25175267Swollman memcpy(Addr, pData, DataSize); 25214343Swollman 25314343Swollman DEBUG(dbgs() << "emitSection SectionID: " << SectionID 25414343Swollman << " obj addr: " << format("%p", pData) 25514343Swollman << " new addr: " << format("%p", Addr) 25619878Swollman << " DataSize: " << DataSize 25719878Swollman << " StubBufSize: " << StubBufSize 25814343Swollman << " Allocate: " << Allocate 25919878Swollman << "\n"); 26019878Swollman } 26119878Swollman else { 26214343Swollman // Even if we didn't load the section, we need to record an entry for it 26314343Swollman // to handle later processing (and by 'handle' I mean don't do anything 26414343Swollman // with these sections). 26514343Swollman Allocate = 0; 26619878Swollman Addr = 0; 26719878Swollman DEBUG(dbgs() << "emitSection SectionID: " << SectionID 26814343Swollman << " obj addr: " << format("%p", data.data()) 26919878Swollman << " new addr: 0" 27014343Swollman << " DataSize: " << DataSize 27119878Swollman << " StubBufSize: " << StubBufSize 27214343Swollman << " Allocate: " << Allocate 27358787Sru << "\n"); 27458787Sru } 27558787Sru 27614343Swollman Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData)); 2772742Swollman return SectionID; 2782742Swollman} 2792742Swollman 28019878Swollmanunsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section, 2812742Swollman bool IsCode, 28219878Swollman ObjSectionToIDMap &LocalSections) { 28319878Swollman 2842742Swollman unsigned SectionID = 0; 2852742Swollman ObjSectionToIDMap::iterator i = LocalSections.find(Section); 2862742Swollman if (i != LocalSections.end()) 28719878Swollman SectionID = i->second; 28819878Swollman else { 28943014Swollman SectionID = emitSection(Section, IsCode); 29058787Sru LocalSections[Section] = SectionID; 29143014Swollman } 2922742Swollman return SectionID; 2932742Swollman} 2942742Swollman 2952742Swollmanvoid RuntimeDyldImpl::AddRelocation(const RelocationValueRef &Value, 2962742Swollman unsigned SectionID, uintptr_t Offset, 2972742Swollman uint32_t RelType) { 2982742Swollman DEBUG(dbgs() << "AddRelocation SymNamePtr: " << format("%p", Value.SymbolName) 2992742Swollman << " SID: " << Value.SectionID 3002742Swollman << " Addend: " << format("%p", Value.Addend) 3012742Swollman << " Offset: " << format("%p", Offset) 3022742Swollman << " RelType: " << format("%x", RelType) 3032742Swollman << "\n"); 30414343Swollman 3052742Swollman if (Value.SymbolName == 0) { 30614343Swollman Relocations[Value.SectionID].push_back(RelocationEntry( 30714343Swollman SectionID, 3082742Swollman Offset, 30914343Swollman RelType, 31043014Swollman Value.Addend)); 31114343Swollman } else 31214343Swollman SymbolRelocations[Value.SymbolName].push_back(RelocationEntry( 31314343Swollman SectionID, 3149908Swollman Offset, 3159908Swollman RelType, 3169908Swollman Value.Addend)); 3179908Swollman} 3189908Swollman 3199908Swollmanuint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { 3209908Swollman // TODO: There is only ARM far stub now. We should add the Thumb stub, 32120094Swollman // and stubs for branches Thumb - ARM and ARM - Thumb. 32220094Swollman if (Arch == Triple::arm) { 3232742Swollman uint32_t *StubAddr = (uint32_t*)Addr; 3242742Swollman *StubAddr = 0xe51ff004; // ldr pc,<label> 32514343Swollman return (uint8_t*)++StubAddr; 3262742Swollman } 32720094Swollman else 3282742Swollman return Addr; 3298029Swollman} 33030711Swollman 33158787Sru// Assign an address to a symbol name and resolve all the relocations 33258787Sru// associated with it. 3332742Swollmanvoid RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID, 33430711Swollman uint64_t Addr) { 33558787Sru // The address to use for relocation resolution is not 33658787Sru // the address of the local section buffer. We must be doing 33758787Sru // a remote execution environment of some sort. Re-apply any 33830711Swollman // relocations referencing this section with the given address. 33930711Swollman // 3402742Swollman // Addr is a uint64_t because we can't assume the pointer width 3412742Swollman // of the target is the same as that of the host. Just use a generic 3422742Swollman // "big enough" type. 3432742Swollman Sections[SectionID].LoadAddress = Addr; 3442742Swollman DEBUG(dbgs() << "Resolving relocations Section #" << SectionID 3452742Swollman << "\t" << format("%p", (uint8_t *)Addr) 34619878Swollman << "\n"); 34719878Swollman resolveRelocationList(Relocations[SectionID], Addr); 34819878Swollman} 3492742Swollman 3502742Swollmanvoid RuntimeDyldImpl::resolveRelocationEntry(const RelocationEntry &RE, 3512742Swollman uint64_t Value) { 3522742Swollman // Ignore relocations for sections that were not loaded 35319878Swollman if (Sections[RE.SectionID].Address != 0) { 35419878Swollman uint8_t *Target = Sections[RE.SectionID].Address + RE.Offset; 3552742Swollman DEBUG(dbgs() << "\tSectionID: " << RE.SectionID 35658787Sru << " + " << RE.Offset << " (" << format("%p", Target) << ")" 3579908Swollman << " Data: " << RE.Data 3589908Swollman << " Addend: " << RE.Addend 35919878Swollman << "\n"); 3609908Swollman 3612742Swollman resolveRelocation(Target, Sections[RE.SectionID].LoadAddress + RE.Offset, 3622742Swollman Value, RE.Data, RE.Addend); 3632742Swollman } 36486222Swollman} 36519878Swollman 3662742Swollmanvoid RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, 3672742Swollman uint64_t Value) { 3682742Swollman for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { 3692742Swollman resolveRelocationEntry(Relocs[i], Value); 37058787Sru } 37158787Sru} 3722742Swollman 37314343Swollman// resolveSymbols - Resolve any relocations to the specified symbols if 37414343Swollman// we know where it lives. 37514343Swollmanvoid RuntimeDyldImpl::resolveSymbols() { 37619878Swollman StringMap<RelocationList>::iterator i = SymbolRelocations.begin(), 37714343Swollman e = SymbolRelocations.end(); 37814343Swollman for (; i != e; i++) { 37914343Swollman StringRef Name = i->first(); 38014343Swollman RelocationList &Relocs = i->second; 38114343Swollman StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(Name); 38214343Swollman if (Loc == SymbolTable.end()) { 38314343Swollman // This is an external symbol, try to get it address from 38419878Swollman // MemoryManager. 38519878Swollman uint8_t *Addr = (uint8_t*) MemMgr->getPointerToNamedFunction(Name.data(), 38614343Swollman true); 3872742Swollman DEBUG(dbgs() << "Resolving relocations Name: " << Name 3882742Swollman << "\t" << format("%p", Addr) 3892742Swollman << "\n"); 3902742Swollman resolveRelocationList(Relocs, (uintptr_t)Addr); 39119878Swollman } else { 3922742Swollman // Change the relocation to be section relative rather than symbol 3932742Swollman // relative and move it to the resolved relocation list. 3942742Swollman DEBUG(dbgs() << "Resolving symbol '" << Name << "'\n"); 3952742Swollman for (int i = 0, e = Relocs.size(); i != e; ++i) { 39619878Swollman RelocationEntry Entry = Relocs[i]; 3972742Swollman Entry.Addend += Loc->second.second; 3982742Swollman Relocations[Loc->second.first].push_back(Entry); 39958787Sru } 40075267Swollman Relocs.clear(); 40175267Swollman } 40293799Swollman } 40393799Swollman} 4042742Swollman 4052742Swollman 40658787Sru//===----------------------------------------------------------------------===// 40758787Sru// RuntimeDyld class implementation 40858787SruRuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { 4092742Swollman Dyld = 0; 4102742Swollman MM = mm; 4112742Swollman} 4122742Swollman 41319878SwollmanRuntimeDyld::~RuntimeDyld() { 4142742Swollman delete Dyld; 41543014Swollman} 41643014Swollman 41743014Swollmanbool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { 41843014Swollman if (!Dyld) { 41943014Swollman sys::LLVMFileType type = sys::IdentifyFileType( 42043014Swollman InputBuffer->getBufferStart(), 42143014Swollman static_cast<unsigned>(InputBuffer->getBufferSize())); 42243014Swollman switch (type) { 42343014Swollman case sys::ELF_Relocatable_FileType: 42443014Swollman case sys::ELF_Executable_FileType: 42543014Swollman case sys::ELF_SharedObject_FileType: 42643014Swollman case sys::ELF_Core_FileType: 42743014Swollman Dyld = new RuntimeDyldELF(MM); 42843014Swollman break; 42943014Swollman case sys::Mach_O_Object_FileType: 43043014Swollman case sys::Mach_O_Executable_FileType: 43143014Swollman case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: 43243014Swollman case sys::Mach_O_Core_FileType: 43343014Swollman case sys::Mach_O_PreloadExecutable_FileType: 43443014Swollman case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: 43543014Swollman case sys::Mach_O_DynamicLinker_FileType: 43643014Swollman case sys::Mach_O_Bundle_FileType: 43743014Swollman case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: 43843014Swollman case sys::Mach_O_DSYMCompanion_FileType: 43943014Swollman Dyld = new RuntimeDyldMachO(MM); 44043014Swollman break; 44143014Swollman case sys::Unknown_FileType: 44243014Swollman case sys::Bitcode_FileType: 44343014Swollman case sys::Archive_FileType: 44443014Swollman case sys::COFF_FileType: 44543014Swollman report_fatal_error("Incompatible object format!"); 44643014Swollman } 44743014Swollman } else { 4482742Swollman if (!Dyld->isCompatibleFormat(InputBuffer)) 4492742Swollman report_fatal_error("Incompatible object format!"); 45019878Swollman } 45119878Swollman 45219878Swollman return Dyld->loadObject(InputBuffer); 45320094Swollman} 45420094Swollman 45520094Swollmanvoid *RuntimeDyld::getSymbolAddress(StringRef Name) { 4562742Swollman return Dyld->getSymbolAddress(Name); 4572742Swollman} 45819878Swollman 4592742Swollmanvoid RuntimeDyld::resolveRelocations() { 4602742Swollman Dyld->resolveRelocations(); 4612742Swollman} 4622742Swollman 46319878Swollmanvoid RuntimeDyld::reassignSectionAddress(unsigned SectionID, 4642742Swollman uint64_t Addr) { 4652742Swollman Dyld->reassignSectionAddress(SectionID, Addr); 4662742Swollman} 4672742Swollman 4682742Swollmanvoid RuntimeDyld::mapSectionAddress(void *LocalAddress, 4692742Swollman uint64_t TargetAddress) { 4702742Swollman Dyld->mapSectionAddress(LocalAddress, TargetAddress); 4712742Swollman} 4722742Swollman 47358787SruStringRef RuntimeDyld::getErrorString() { 4742742Swollman return Dyld->getErrorString(); 47558787Sru} 47658787Sru 4772742Swollman} // end namespace llvm 47886222Swollman