LTOModule.cpp revision 259698
1259698Sdim//===-- LTOModule.cpp - LLVM Link Time Optimizer --------------------------===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim// 10259698Sdim// This file implements the Link Time Optimization library. This library is 11259698Sdim// intended to be used by linker to optimize code at link time. 12259698Sdim// 13259698Sdim//===----------------------------------------------------------------------===// 14259698Sdim 15259698Sdim#include "llvm/LTO/LTOModule.h" 16259698Sdim#include "llvm/ADT/OwningPtr.h" 17259698Sdim#include "llvm/ADT/Triple.h" 18259698Sdim#include "llvm/Bitcode/ReaderWriter.h" 19259698Sdim#include "llvm/IR/Constants.h" 20259698Sdim#include "llvm/IR/LLVMContext.h" 21259698Sdim#include "llvm/IR/Module.h" 22259698Sdim#include "llvm/MC/MCExpr.h" 23259698Sdim#include "llvm/MC/MCInst.h" 24259698Sdim#include "llvm/MC/MCInstrInfo.h" 25259698Sdim#include "llvm/MC/MCParser/MCAsmParser.h" 26259698Sdim#include "llvm/MC/MCStreamer.h" 27259698Sdim#include "llvm/MC/MCSubtargetInfo.h" 28259698Sdim#include "llvm/MC/MCSymbol.h" 29259698Sdim#include "llvm/MC/MCTargetAsmParser.h" 30259698Sdim#include "llvm/MC/SubtargetFeature.h" 31259698Sdim#include "llvm/Support/CommandLine.h" 32259698Sdim#include "llvm/Support/Host.h" 33259698Sdim#include "llvm/Support/FileSystem.h" 34259698Sdim#include "llvm/Support/MemoryBuffer.h" 35259698Sdim#include "llvm/Support/Path.h" 36259698Sdim#include "llvm/Support/SourceMgr.h" 37259698Sdim#include "llvm/Support/TargetRegistry.h" 38259698Sdim#include "llvm/Support/TargetSelect.h" 39259698Sdim#include "llvm/Support/system_error.h" 40259698Sdim#include "llvm/Target/TargetRegisterInfo.h" 41259698Sdim#include "llvm/Transforms/Utils/GlobalStatus.h" 42259698Sdimusing namespace llvm; 43259698Sdim 44259698SdimLTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t) 45259698Sdim : _module(m), _target(t), 46259698Sdim _context(_target->getMCAsmInfo(), _target->getRegisterInfo(), NULL), 47259698Sdim _mangler(t) {} 48259698Sdim 49259698Sdim/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM 50259698Sdim/// bitcode. 51259698Sdimbool LTOModule::isBitcodeFile(const void *mem, size_t length) { 52259698Sdim return sys::fs::identify_magic(StringRef((const char *)mem, length)) == 53259698Sdim sys::fs::file_magic::bitcode; 54259698Sdim} 55259698Sdim 56259698Sdimbool LTOModule::isBitcodeFile(const char *path) { 57259698Sdim sys::fs::file_magic type; 58259698Sdim if (sys::fs::identify_magic(path, type)) 59259698Sdim return false; 60259698Sdim return type == sys::fs::file_magic::bitcode; 61259698Sdim} 62259698Sdim 63259698Sdim/// isBitcodeFileForTarget - Returns 'true' if the file (or memory contents) is 64259698Sdim/// LLVM bitcode for the specified triple. 65259698Sdimbool LTOModule::isBitcodeFileForTarget(const void *mem, size_t length, 66259698Sdim const char *triplePrefix) { 67259698Sdim MemoryBuffer *buffer = makeBuffer(mem, length); 68259698Sdim if (!buffer) 69259698Sdim return false; 70259698Sdim return isTargetMatch(buffer, triplePrefix); 71259698Sdim} 72259698Sdim 73259698Sdimbool LTOModule::isBitcodeFileForTarget(const char *path, 74259698Sdim const char *triplePrefix) { 75259698Sdim OwningPtr<MemoryBuffer> buffer; 76259698Sdim if (MemoryBuffer::getFile(path, buffer)) 77259698Sdim return false; 78259698Sdim return isTargetMatch(buffer.take(), triplePrefix); 79259698Sdim} 80259698Sdim 81259698Sdim/// isTargetMatch - Returns 'true' if the memory buffer is for the specified 82259698Sdim/// target triple. 83259698Sdimbool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) { 84259698Sdim std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); 85259698Sdim delete buffer; 86259698Sdim return strncmp(Triple.c_str(), triplePrefix, strlen(triplePrefix)) == 0; 87259698Sdim} 88259698Sdim 89259698Sdim/// makeLTOModule - Create an LTOModule. N.B. These methods take ownership of 90259698Sdim/// the buffer. 91259698SdimLTOModule *LTOModule::makeLTOModule(const char *path, TargetOptions options, 92259698Sdim std::string &errMsg) { 93259698Sdim OwningPtr<MemoryBuffer> buffer; 94259698Sdim if (error_code ec = MemoryBuffer::getFile(path, buffer)) { 95259698Sdim errMsg = ec.message(); 96259698Sdim return NULL; 97259698Sdim } 98259698Sdim return makeLTOModule(buffer.take(), options, errMsg); 99259698Sdim} 100259698Sdim 101259698SdimLTOModule *LTOModule::makeLTOModule(int fd, const char *path, 102259698Sdim size_t size, TargetOptions options, 103259698Sdim std::string &errMsg) { 104259698Sdim return makeLTOModule(fd, path, size, 0, options, errMsg); 105259698Sdim} 106259698Sdim 107259698SdimLTOModule *LTOModule::makeLTOModule(int fd, const char *path, 108259698Sdim size_t map_size, 109259698Sdim off_t offset, 110259698Sdim TargetOptions options, 111259698Sdim std::string &errMsg) { 112259698Sdim OwningPtr<MemoryBuffer> buffer; 113259698Sdim if (error_code ec = 114259698Sdim MemoryBuffer::getOpenFileSlice(fd, path, buffer, map_size, offset)) { 115259698Sdim errMsg = ec.message(); 116259698Sdim return NULL; 117259698Sdim } 118259698Sdim return makeLTOModule(buffer.take(), options, errMsg); 119259698Sdim} 120259698Sdim 121259698SdimLTOModule *LTOModule::makeLTOModule(const void *mem, size_t length, 122259698Sdim TargetOptions options, 123259698Sdim std::string &errMsg) { 124259698Sdim OwningPtr<MemoryBuffer> buffer(makeBuffer(mem, length)); 125259698Sdim if (!buffer) 126259698Sdim return NULL; 127259698Sdim return makeLTOModule(buffer.take(), options, errMsg); 128259698Sdim} 129259698Sdim 130259698SdimLTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer, 131259698Sdim TargetOptions options, 132259698Sdim std::string &errMsg) { 133259698Sdim // parse bitcode buffer 134259698Sdim OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext(), 135259698Sdim &errMsg)); 136259698Sdim if (!m) { 137259698Sdim delete buffer; 138259698Sdim return NULL; 139259698Sdim } 140259698Sdim 141259698Sdim std::string TripleStr = m->getTargetTriple(); 142259698Sdim if (TripleStr.empty()) 143259698Sdim TripleStr = sys::getDefaultTargetTriple(); 144259698Sdim llvm::Triple Triple(TripleStr); 145259698Sdim 146259698Sdim // find machine architecture for this module 147259698Sdim const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); 148259698Sdim if (!march) 149259698Sdim return NULL; 150259698Sdim 151259698Sdim // construct LTOModule, hand over ownership of module and target 152259698Sdim SubtargetFeatures Features; 153259698Sdim Features.getDefaultSubtargetFeatures(Triple); 154259698Sdim std::string FeatureStr = Features.getString(); 155259698Sdim // Set a default CPU for Darwin triples. 156259698Sdim std::string CPU; 157259698Sdim if (Triple.isOSDarwin()) { 158259698Sdim if (Triple.getArch() == llvm::Triple::x86_64) 159259698Sdim CPU = "core2"; 160259698Sdim else if (Triple.getArch() == llvm::Triple::x86) 161259698Sdim CPU = "yonah"; 162259698Sdim } 163259698Sdim 164259698Sdim TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, 165259698Sdim options); 166259698Sdim m->MaterializeAllPermanently(); 167259698Sdim 168259698Sdim LTOModule *Ret = new LTOModule(m.take(), target); 169259698Sdim if (Ret->parseSymbols(errMsg)) { 170259698Sdim delete Ret; 171259698Sdim return NULL; 172259698Sdim } 173259698Sdim 174259698Sdim return Ret; 175259698Sdim} 176259698Sdim 177259698Sdim/// makeBuffer - Create a MemoryBuffer from a memory range. 178259698SdimMemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) { 179259698Sdim const char *startPtr = (const char*)mem; 180259698Sdim return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false); 181259698Sdim} 182259698Sdim 183259698Sdim/// objcClassNameFromExpression - Get string that the data pointer points to. 184259698Sdimbool 185259698SdimLTOModule::objcClassNameFromExpression(const Constant *c, std::string &name) { 186259698Sdim if (const ConstantExpr *ce = dyn_cast<ConstantExpr>(c)) { 187259698Sdim Constant *op = ce->getOperand(0); 188259698Sdim if (GlobalVariable *gvn = dyn_cast<GlobalVariable>(op)) { 189259698Sdim Constant *cn = gvn->getInitializer(); 190259698Sdim if (ConstantDataArray *ca = dyn_cast<ConstantDataArray>(cn)) { 191259698Sdim if (ca->isCString()) { 192259698Sdim name = ".objc_class_name_" + ca->getAsCString().str(); 193259698Sdim return true; 194259698Sdim } 195259698Sdim } 196259698Sdim } 197259698Sdim } 198259698Sdim return false; 199259698Sdim} 200259698Sdim 201259698Sdim/// addObjCClass - Parse i386/ppc ObjC class data structure. 202259698Sdimvoid LTOModule::addObjCClass(const GlobalVariable *clgv) { 203259698Sdim const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); 204259698Sdim if (!c) return; 205259698Sdim 206259698Sdim // second slot in __OBJC,__class is pointer to superclass name 207259698Sdim std::string superclassName; 208259698Sdim if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { 209259698Sdim NameAndAttributes info; 210259698Sdim StringMap<NameAndAttributes>::value_type &entry = 211259698Sdim _undefines.GetOrCreateValue(superclassName); 212259698Sdim if (!entry.getValue().name) { 213259698Sdim const char *symbolName = entry.getKey().data(); 214259698Sdim info.name = symbolName; 215259698Sdim info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; 216259698Sdim info.isFunction = false; 217259698Sdim info.symbol = clgv; 218259698Sdim entry.setValue(info); 219259698Sdim } 220259698Sdim } 221259698Sdim 222259698Sdim // third slot in __OBJC,__class is pointer to class name 223259698Sdim std::string className; 224259698Sdim if (objcClassNameFromExpression(c->getOperand(2), className)) { 225259698Sdim StringSet::value_type &entry = _defines.GetOrCreateValue(className); 226259698Sdim entry.setValue(1); 227259698Sdim 228259698Sdim NameAndAttributes info; 229259698Sdim info.name = entry.getKey().data(); 230259698Sdim info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | 231259698Sdim LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; 232259698Sdim info.isFunction = false; 233259698Sdim info.symbol = clgv; 234259698Sdim _symbols.push_back(info); 235259698Sdim } 236259698Sdim} 237259698Sdim 238259698Sdim/// addObjCCategory - Parse i386/ppc ObjC category data structure. 239259698Sdimvoid LTOModule::addObjCCategory(const GlobalVariable *clgv) { 240259698Sdim const ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer()); 241259698Sdim if (!c) return; 242259698Sdim 243259698Sdim // second slot in __OBJC,__category is pointer to target class name 244259698Sdim std::string targetclassName; 245259698Sdim if (!objcClassNameFromExpression(c->getOperand(1), targetclassName)) 246259698Sdim return; 247259698Sdim 248259698Sdim NameAndAttributes info; 249259698Sdim StringMap<NameAndAttributes>::value_type &entry = 250259698Sdim _undefines.GetOrCreateValue(targetclassName); 251259698Sdim 252259698Sdim if (entry.getValue().name) 253259698Sdim return; 254259698Sdim 255259698Sdim const char *symbolName = entry.getKey().data(); 256259698Sdim info.name = symbolName; 257259698Sdim info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; 258259698Sdim info.isFunction = false; 259259698Sdim info.symbol = clgv; 260259698Sdim entry.setValue(info); 261259698Sdim} 262259698Sdim 263259698Sdim/// addObjCClassRef - Parse i386/ppc ObjC class list data structure. 264259698Sdimvoid LTOModule::addObjCClassRef(const GlobalVariable *clgv) { 265259698Sdim std::string targetclassName; 266259698Sdim if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) 267259698Sdim return; 268259698Sdim 269259698Sdim NameAndAttributes info; 270259698Sdim StringMap<NameAndAttributes>::value_type &entry = 271259698Sdim _undefines.GetOrCreateValue(targetclassName); 272259698Sdim if (entry.getValue().name) 273259698Sdim return; 274259698Sdim 275259698Sdim const char *symbolName = entry.getKey().data(); 276259698Sdim info.name = symbolName; 277259698Sdim info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; 278259698Sdim info.isFunction = false; 279259698Sdim info.symbol = clgv; 280259698Sdim entry.setValue(info); 281259698Sdim} 282259698Sdim 283259698Sdim/// addDefinedDataSymbol - Add a data symbol as defined to the list. 284259698Sdimvoid LTOModule::addDefinedDataSymbol(const GlobalValue *v) { 285259698Sdim // Add to list of defined symbols. 286259698Sdim addDefinedSymbol(v, false); 287259698Sdim 288259698Sdim if (!v->hasSection() /* || !isTargetDarwin */) 289259698Sdim return; 290259698Sdim 291259698Sdim // Special case i386/ppc ObjC data structures in magic sections: 292259698Sdim // The issue is that the old ObjC object format did some strange 293259698Sdim // contortions to avoid real linker symbols. For instance, the 294259698Sdim // ObjC class data structure is allocated statically in the executable 295259698Sdim // that defines that class. That data structures contains a pointer to 296259698Sdim // its superclass. But instead of just initializing that part of the 297259698Sdim // struct to the address of its superclass, and letting the static and 298259698Sdim // dynamic linkers do the rest, the runtime works by having that field 299259698Sdim // instead point to a C-string that is the name of the superclass. 300259698Sdim // At runtime the objc initialization updates that pointer and sets 301259698Sdim // it to point to the actual super class. As far as the linker 302259698Sdim // knows it is just a pointer to a string. But then someone wanted the 303259698Sdim // linker to issue errors at build time if the superclass was not found. 304259698Sdim // So they figured out a way in mach-o object format to use an absolute 305259698Sdim // symbols (.objc_class_name_Foo = 0) and a floating reference 306259698Sdim // (.reference .objc_class_name_Bar) to cause the linker into erroring when 307259698Sdim // a class was missing. 308259698Sdim // The following synthesizes the implicit .objc_* symbols for the linker 309259698Sdim // from the ObjC data structures generated by the front end. 310259698Sdim 311259698Sdim // special case if this data blob is an ObjC class definition 312259698Sdim if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { 313259698Sdim if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { 314259698Sdim addObjCClass(gv); 315259698Sdim } 316259698Sdim } 317259698Sdim 318259698Sdim // special case if this data blob is an ObjC category definition 319259698Sdim else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { 320259698Sdim if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { 321259698Sdim addObjCCategory(gv); 322259698Sdim } 323259698Sdim } 324259698Sdim 325259698Sdim // special case if this data blob is the list of referenced classes 326259698Sdim else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { 327259698Sdim if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { 328259698Sdim addObjCClassRef(gv); 329259698Sdim } 330259698Sdim } 331259698Sdim} 332259698Sdim 333259698Sdim/// addDefinedFunctionSymbol - Add a function symbol as defined to the list. 334259698Sdimvoid LTOModule::addDefinedFunctionSymbol(const Function *f) { 335259698Sdim // add to list of defined symbols 336259698Sdim addDefinedSymbol(f, true); 337259698Sdim} 338259698Sdim 339259698Sdimstatic bool canBeHidden(const GlobalValue *GV) { 340259698Sdim GlobalValue::LinkageTypes L = GV->getLinkage(); 341259698Sdim 342259698Sdim if (L != GlobalValue::LinkOnceODRLinkage) 343259698Sdim return false; 344259698Sdim 345259698Sdim if (GV->hasUnnamedAddr()) 346259698Sdim return true; 347259698Sdim 348259698Sdim GlobalStatus GS; 349259698Sdim if (GlobalStatus::analyzeGlobal(GV, GS)) 350259698Sdim return false; 351259698Sdim 352259698Sdim return !GS.IsCompared; 353259698Sdim} 354259698Sdim 355259698Sdim/// addDefinedSymbol - Add a defined symbol to the list. 356259698Sdimvoid LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) { 357259698Sdim // ignore all llvm.* symbols 358259698Sdim if (def->getName().startswith("llvm.")) 359259698Sdim return; 360259698Sdim 361259698Sdim // string is owned by _defines 362259698Sdim SmallString<64> Buffer; 363259698Sdim _mangler.getNameWithPrefix(Buffer, def, false); 364259698Sdim 365259698Sdim // set alignment part log2() can have rounding errors 366259698Sdim uint32_t align = def->getAlignment(); 367259698Sdim uint32_t attr = align ? countTrailingZeros(def->getAlignment()) : 0; 368259698Sdim 369259698Sdim // set permissions part 370259698Sdim if (isFunction) { 371259698Sdim attr |= LTO_SYMBOL_PERMISSIONS_CODE; 372259698Sdim } else { 373259698Sdim const GlobalVariable *gv = dyn_cast<GlobalVariable>(def); 374259698Sdim if (gv && gv->isConstant()) 375259698Sdim attr |= LTO_SYMBOL_PERMISSIONS_RODATA; 376259698Sdim else 377259698Sdim attr |= LTO_SYMBOL_PERMISSIONS_DATA; 378259698Sdim } 379259698Sdim 380259698Sdim // set definition part 381259698Sdim if (def->hasWeakLinkage() || def->hasLinkOnceLinkage() || 382259698Sdim def->hasLinkerPrivateWeakLinkage()) 383259698Sdim attr |= LTO_SYMBOL_DEFINITION_WEAK; 384259698Sdim else if (def->hasCommonLinkage()) 385259698Sdim attr |= LTO_SYMBOL_DEFINITION_TENTATIVE; 386259698Sdim else 387259698Sdim attr |= LTO_SYMBOL_DEFINITION_REGULAR; 388259698Sdim 389259698Sdim // set scope part 390259698Sdim if (def->hasHiddenVisibility()) 391259698Sdim attr |= LTO_SYMBOL_SCOPE_HIDDEN; 392259698Sdim else if (def->hasProtectedVisibility()) 393259698Sdim attr |= LTO_SYMBOL_SCOPE_PROTECTED; 394259698Sdim else if (canBeHidden(def)) 395259698Sdim attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; 396259698Sdim else if (def->hasExternalLinkage() || def->hasWeakLinkage() || 397259698Sdim def->hasLinkOnceLinkage() || def->hasCommonLinkage() || 398259698Sdim def->hasLinkerPrivateWeakLinkage()) 399259698Sdim attr |= LTO_SYMBOL_SCOPE_DEFAULT; 400259698Sdim else 401259698Sdim attr |= LTO_SYMBOL_SCOPE_INTERNAL; 402259698Sdim 403259698Sdim StringSet::value_type &entry = _defines.GetOrCreateValue(Buffer); 404259698Sdim entry.setValue(1); 405259698Sdim 406259698Sdim // fill information structure 407259698Sdim NameAndAttributes info; 408259698Sdim StringRef Name = entry.getKey(); 409259698Sdim info.name = Name.data(); 410259698Sdim assert(info.name[Name.size()] == '\0'); 411259698Sdim info.attributes = attr; 412259698Sdim info.isFunction = isFunction; 413259698Sdim info.symbol = def; 414259698Sdim 415259698Sdim // add to table of symbols 416259698Sdim _symbols.push_back(info); 417259698Sdim} 418259698Sdim 419259698Sdim/// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the 420259698Sdim/// defined list. 421259698Sdimvoid LTOModule::addAsmGlobalSymbol(const char *name, 422259698Sdim lto_symbol_attributes scope) { 423259698Sdim StringSet::value_type &entry = _defines.GetOrCreateValue(name); 424259698Sdim 425259698Sdim // only add new define if not already defined 426259698Sdim if (entry.getValue()) 427259698Sdim return; 428259698Sdim 429259698Sdim entry.setValue(1); 430259698Sdim 431259698Sdim NameAndAttributes &info = _undefines[entry.getKey().data()]; 432259698Sdim 433259698Sdim if (info.symbol == 0) { 434259698Sdim // FIXME: This is trying to take care of module ASM like this: 435259698Sdim // 436259698Sdim // module asm ".zerofill __FOO, __foo, _bar_baz_qux, 0" 437259698Sdim // 438259698Sdim // but is gross and its mother dresses it funny. Have the ASM parser give us 439259698Sdim // more details for this type of situation so that we're not guessing so 440259698Sdim // much. 441259698Sdim 442259698Sdim // fill information structure 443259698Sdim info.name = entry.getKey().data(); 444259698Sdim info.attributes = 445259698Sdim LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; 446259698Sdim info.isFunction = false; 447259698Sdim info.symbol = 0; 448259698Sdim 449259698Sdim // add to table of symbols 450259698Sdim _symbols.push_back(info); 451259698Sdim return; 452259698Sdim } 453259698Sdim 454259698Sdim if (info.isFunction) 455259698Sdim addDefinedFunctionSymbol(cast<Function>(info.symbol)); 456259698Sdim else 457259698Sdim addDefinedDataSymbol(info.symbol); 458259698Sdim 459259698Sdim _symbols.back().attributes &= ~LTO_SYMBOL_SCOPE_MASK; 460259698Sdim _symbols.back().attributes |= scope; 461259698Sdim} 462259698Sdim 463259698Sdim/// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the 464259698Sdim/// undefined list. 465259698Sdimvoid LTOModule::addAsmGlobalSymbolUndef(const char *name) { 466259698Sdim StringMap<NameAndAttributes>::value_type &entry = 467259698Sdim _undefines.GetOrCreateValue(name); 468259698Sdim 469259698Sdim _asm_undefines.push_back(entry.getKey().data()); 470259698Sdim 471259698Sdim // we already have the symbol 472259698Sdim if (entry.getValue().name) 473259698Sdim return; 474259698Sdim 475259698Sdim uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED;; 476259698Sdim attr |= LTO_SYMBOL_SCOPE_DEFAULT; 477259698Sdim NameAndAttributes info; 478259698Sdim info.name = entry.getKey().data(); 479259698Sdim info.attributes = attr; 480259698Sdim info.isFunction = false; 481259698Sdim info.symbol = 0; 482259698Sdim 483259698Sdim entry.setValue(info); 484259698Sdim} 485259698Sdim 486259698Sdim/// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet to a 487259698Sdim/// list to be resolved later. 488259698Sdimvoid 489259698SdimLTOModule::addPotentialUndefinedSymbol(const GlobalValue *decl, bool isFunc) { 490259698Sdim // ignore all llvm.* symbols 491259698Sdim if (decl->getName().startswith("llvm.")) 492259698Sdim return; 493259698Sdim 494259698Sdim // ignore all aliases 495259698Sdim if (isa<GlobalAlias>(decl)) 496259698Sdim return; 497259698Sdim 498259698Sdim SmallString<64> name; 499259698Sdim _mangler.getNameWithPrefix(name, decl, false); 500259698Sdim 501259698Sdim StringMap<NameAndAttributes>::value_type &entry = 502259698Sdim _undefines.GetOrCreateValue(name); 503259698Sdim 504259698Sdim // we already have the symbol 505259698Sdim if (entry.getValue().name) 506259698Sdim return; 507259698Sdim 508259698Sdim NameAndAttributes info; 509259698Sdim 510259698Sdim info.name = entry.getKey().data(); 511259698Sdim 512259698Sdim if (decl->hasExternalWeakLinkage()) 513259698Sdim info.attributes = LTO_SYMBOL_DEFINITION_WEAKUNDEF; 514259698Sdim else 515259698Sdim info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; 516259698Sdim 517259698Sdim info.isFunction = isFunc; 518259698Sdim info.symbol = decl; 519259698Sdim 520259698Sdim entry.setValue(info); 521259698Sdim} 522259698Sdim 523259698Sdimnamespace { 524259698Sdim class RecordStreamer : public MCStreamer { 525259698Sdim public: 526259698Sdim enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; 527259698Sdim 528259698Sdim private: 529259698Sdim StringMap<State> Symbols; 530259698Sdim 531259698Sdim void markDefined(const MCSymbol &Symbol) { 532259698Sdim State &S = Symbols[Symbol.getName()]; 533259698Sdim switch (S) { 534259698Sdim case DefinedGlobal: 535259698Sdim case Global: 536259698Sdim S = DefinedGlobal; 537259698Sdim break; 538259698Sdim case NeverSeen: 539259698Sdim case Defined: 540259698Sdim case Used: 541259698Sdim S = Defined; 542259698Sdim break; 543259698Sdim } 544259698Sdim } 545259698Sdim void markGlobal(const MCSymbol &Symbol) { 546259698Sdim State &S = Symbols[Symbol.getName()]; 547259698Sdim switch (S) { 548259698Sdim case DefinedGlobal: 549259698Sdim case Defined: 550259698Sdim S = DefinedGlobal; 551259698Sdim break; 552259698Sdim 553259698Sdim case NeverSeen: 554259698Sdim case Global: 555259698Sdim case Used: 556259698Sdim S = Global; 557259698Sdim break; 558259698Sdim } 559259698Sdim } 560259698Sdim void markUsed(const MCSymbol &Symbol) { 561259698Sdim State &S = Symbols[Symbol.getName()]; 562259698Sdim switch (S) { 563259698Sdim case DefinedGlobal: 564259698Sdim case Defined: 565259698Sdim case Global: 566259698Sdim break; 567259698Sdim 568259698Sdim case NeverSeen: 569259698Sdim case Used: 570259698Sdim S = Used; 571259698Sdim break; 572259698Sdim } 573259698Sdim } 574259698Sdim 575259698Sdim // FIXME: mostly copied for the obj streamer. 576259698Sdim void AddValueSymbols(const MCExpr *Value) { 577259698Sdim switch (Value->getKind()) { 578259698Sdim case MCExpr::Target: 579259698Sdim // FIXME: What should we do in here? 580259698Sdim break; 581259698Sdim 582259698Sdim case MCExpr::Constant: 583259698Sdim break; 584259698Sdim 585259698Sdim case MCExpr::Binary: { 586259698Sdim const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); 587259698Sdim AddValueSymbols(BE->getLHS()); 588259698Sdim AddValueSymbols(BE->getRHS()); 589259698Sdim break; 590259698Sdim } 591259698Sdim 592259698Sdim case MCExpr::SymbolRef: 593259698Sdim markUsed(cast<MCSymbolRefExpr>(Value)->getSymbol()); 594259698Sdim break; 595259698Sdim 596259698Sdim case MCExpr::Unary: 597259698Sdim AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); 598259698Sdim break; 599259698Sdim } 600259698Sdim } 601259698Sdim 602259698Sdim public: 603259698Sdim typedef StringMap<State>::const_iterator const_iterator; 604259698Sdim 605259698Sdim const_iterator begin() { 606259698Sdim return Symbols.begin(); 607259698Sdim } 608259698Sdim 609259698Sdim const_iterator end() { 610259698Sdim return Symbols.end(); 611259698Sdim } 612259698Sdim 613259698Sdim RecordStreamer(MCContext &Context) : MCStreamer(Context, 0) {} 614259698Sdim 615259698Sdim virtual void EmitInstruction(const MCInst &Inst) { 616259698Sdim // Scan for values. 617259698Sdim for (unsigned i = Inst.getNumOperands(); i--; ) 618259698Sdim if (Inst.getOperand(i).isExpr()) 619259698Sdim AddValueSymbols(Inst.getOperand(i).getExpr()); 620259698Sdim } 621259698Sdim virtual void EmitLabel(MCSymbol *Symbol) { 622259698Sdim Symbol->setSection(*getCurrentSection().first); 623259698Sdim markDefined(*Symbol); 624259698Sdim } 625259698Sdim virtual void EmitDebugLabel(MCSymbol *Symbol) { 626259698Sdim EmitLabel(Symbol); 627259698Sdim } 628259698Sdim virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 629259698Sdim // FIXME: should we handle aliases? 630259698Sdim markDefined(*Symbol); 631259698Sdim } 632259698Sdim virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { 633259698Sdim if (Attribute == MCSA_Global) 634259698Sdim markGlobal(*Symbol); 635259698Sdim return true; 636259698Sdim } 637259698Sdim virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 638259698Sdim uint64_t Size , unsigned ByteAlignment) { 639259698Sdim markDefined(*Symbol); 640259698Sdim } 641259698Sdim virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 642259698Sdim unsigned ByteAlignment) { 643259698Sdim markDefined(*Symbol); 644259698Sdim } 645259698Sdim 646259698Sdim virtual void EmitBundleAlignMode(unsigned AlignPow2) {} 647259698Sdim virtual void EmitBundleLock(bool AlignToEnd) {} 648259698Sdim virtual void EmitBundleUnlock() {} 649259698Sdim 650259698Sdim // Noop calls. 651259698Sdim virtual void ChangeSection(const MCSection *Section, 652259698Sdim const MCExpr *Subsection) {} 653259698Sdim virtual void InitToTextSection() {} 654259698Sdim virtual void InitSections() {} 655259698Sdim virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} 656259698Sdim virtual void EmitThumbFunc(MCSymbol *Func) {} 657259698Sdim virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} 658259698Sdim virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {} 659259698Sdim virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} 660259698Sdim virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} 661259698Sdim virtual void EmitCOFFSymbolType(int Type) {} 662259698Sdim virtual void EndCOFFSymbolDef() {} 663259698Sdim virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} 664259698Sdim virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 665259698Sdim unsigned ByteAlignment) {} 666259698Sdim virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 667259698Sdim uint64_t Size, unsigned ByteAlignment) {} 668259698Sdim virtual void EmitBytes(StringRef Data) {} 669259698Sdim virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) {} 670259698Sdim virtual void EmitULEB128Value(const MCExpr *Value) {} 671259698Sdim virtual void EmitSLEB128Value(const MCExpr *Value) {} 672259698Sdim virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 673259698Sdim unsigned ValueSize, 674259698Sdim unsigned MaxBytesToEmit) {} 675259698Sdim virtual void EmitCodeAlignment(unsigned ByteAlignment, 676259698Sdim unsigned MaxBytesToEmit) {} 677259698Sdim virtual bool EmitValueToOffset(const MCExpr *Offset, 678259698Sdim unsigned char Value ) { return false; } 679259698Sdim virtual void EmitFileDirective(StringRef Filename) {} 680259698Sdim virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, 681259698Sdim const MCSymbol *LastLabel, 682259698Sdim const MCSymbol *Label, 683259698Sdim unsigned PointerSize) {} 684259698Sdim virtual void FinishImpl() {} 685259698Sdim virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 686259698Sdim RecordProcEnd(Frame); 687259698Sdim } 688259698Sdim }; 689259698Sdim} // end anonymous namespace 690259698Sdim 691259698Sdim/// addAsmGlobalSymbols - Add global symbols from module-level ASM to the 692259698Sdim/// defined or undefined lists. 693259698Sdimbool LTOModule::addAsmGlobalSymbols(std::string &errMsg) { 694259698Sdim const std::string &inlineAsm = _module->getModuleInlineAsm(); 695259698Sdim if (inlineAsm.empty()) 696259698Sdim return false; 697259698Sdim 698259698Sdim OwningPtr<RecordStreamer> Streamer(new RecordStreamer(_context)); 699259698Sdim MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(inlineAsm); 700259698Sdim SourceMgr SrcMgr; 701259698Sdim SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); 702259698Sdim OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, 703259698Sdim _context, *Streamer, 704259698Sdim *_target->getMCAsmInfo())); 705259698Sdim const Target &T = _target->getTarget(); 706259698Sdim OwningPtr<MCInstrInfo> MCII(T.createMCInstrInfo()); 707259698Sdim OwningPtr<MCSubtargetInfo> 708259698Sdim STI(T.createMCSubtargetInfo(_target->getTargetTriple(), 709259698Sdim _target->getTargetCPU(), 710259698Sdim _target->getTargetFeatureString())); 711259698Sdim OwningPtr<MCTargetAsmParser> TAP(T.createMCAsmParser(*STI, *Parser.get(), *MCII)); 712259698Sdim if (!TAP) { 713259698Sdim errMsg = "target " + std::string(T.getName()) + 714259698Sdim " does not define AsmParser."; 715259698Sdim return true; 716259698Sdim } 717259698Sdim 718259698Sdim Parser->setTargetParser(*TAP); 719259698Sdim if (Parser->Run(false)) 720259698Sdim return true; 721259698Sdim 722259698Sdim for (RecordStreamer::const_iterator i = Streamer->begin(), 723259698Sdim e = Streamer->end(); i != e; ++i) { 724259698Sdim StringRef Key = i->first(); 725259698Sdim RecordStreamer::State Value = i->second; 726259698Sdim if (Value == RecordStreamer::DefinedGlobal) 727259698Sdim addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_DEFAULT); 728259698Sdim else if (Value == RecordStreamer::Defined) 729259698Sdim addAsmGlobalSymbol(Key.data(), LTO_SYMBOL_SCOPE_INTERNAL); 730259698Sdim else if (Value == RecordStreamer::Global || 731259698Sdim Value == RecordStreamer::Used) 732259698Sdim addAsmGlobalSymbolUndef(Key.data()); 733259698Sdim } 734259698Sdim 735259698Sdim return false; 736259698Sdim} 737259698Sdim 738259698Sdim/// isDeclaration - Return 'true' if the global value is a declaration. 739259698Sdimstatic bool isDeclaration(const GlobalValue &V) { 740259698Sdim if (V.hasAvailableExternallyLinkage()) 741259698Sdim return true; 742259698Sdim 743259698Sdim if (V.isMaterializable()) 744259698Sdim return false; 745259698Sdim 746259698Sdim return V.isDeclaration(); 747259698Sdim} 748259698Sdim 749259698Sdim/// parseSymbols - Parse the symbols from the module and model-level ASM and add 750259698Sdim/// them to either the defined or undefined lists. 751259698Sdimbool LTOModule::parseSymbols(std::string &errMsg) { 752259698Sdim // add functions 753259698Sdim for (Module::iterator f = _module->begin(), e = _module->end(); f != e; ++f) { 754259698Sdim if (isDeclaration(*f)) 755259698Sdim addPotentialUndefinedSymbol(f, true); 756259698Sdim else 757259698Sdim addDefinedFunctionSymbol(f); 758259698Sdim } 759259698Sdim 760259698Sdim // add data 761259698Sdim for (Module::global_iterator v = _module->global_begin(), 762259698Sdim e = _module->global_end(); v != e; ++v) { 763259698Sdim if (isDeclaration(*v)) 764259698Sdim addPotentialUndefinedSymbol(v, false); 765259698Sdim else 766259698Sdim addDefinedDataSymbol(v); 767259698Sdim } 768259698Sdim 769259698Sdim // add asm globals 770259698Sdim if (addAsmGlobalSymbols(errMsg)) 771259698Sdim return true; 772259698Sdim 773259698Sdim // add aliases 774259698Sdim for (Module::alias_iterator a = _module->alias_begin(), 775259698Sdim e = _module->alias_end(); a != e; ++a) { 776259698Sdim if (isDeclaration(*a->getAliasedGlobal())) 777259698Sdim // Is an alias to a declaration. 778259698Sdim addPotentialUndefinedSymbol(a, false); 779259698Sdim else 780259698Sdim addDefinedDataSymbol(a); 781259698Sdim } 782259698Sdim 783259698Sdim // make symbols for all undefines 784259698Sdim for (StringMap<NameAndAttributes>::iterator u =_undefines.begin(), 785259698Sdim e = _undefines.end(); u != e; ++u) { 786259698Sdim // If this symbol also has a definition, then don't make an undefine because 787259698Sdim // it is a tentative definition. 788259698Sdim if (_defines.count(u->getKey())) continue; 789259698Sdim NameAndAttributes info = u->getValue(); 790259698Sdim _symbols.push_back(info); 791259698Sdim } 792259698Sdim 793259698Sdim return false; 794259698Sdim} 795