From 3eb445feb22647e867a339f4c59b0a716b03a21a Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Mon, 1 Jun 2009 20:33:09 +0000 Subject: [PATCH] libLTO needs to handle i386 magic objc class symbols Parse __OBJC data structures and synthesize magic .objc_ symbols. Also, alter mangler so that objc method names are readable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72700 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/lto/LTOModule.cpp | 160 ++++++++++++++++++++++++++++++++++++---- tools/lto/LTOModule.h | 10 ++- 2 files changed, 152 insertions(+), 18 deletions(-) diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp index 78c8cfe93d3..c769af1e2ed 100644 --- a/tools/lto/LTOModule.cpp +++ b/tools/lto/LTOModule.cpp @@ -14,6 +14,7 @@ #include "LTOModule.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/ADT/OwningPtr.h" @@ -176,11 +177,123 @@ void LTOModule::addDefinedFunctionSymbol(Function* f, Mangler &mangler) } } -void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler) +// get string that data pointer points to +bool LTOModule::objcClassNameFromExpression(Constant* c, std::string& name) +{ + if (ConstantExpr* ce = dyn_cast(c)) { + Constant* op = ce->getOperand(0); + if (GlobalVariable* gvn = dyn_cast(op)) { + Constant* cn = gvn->getInitializer(); + if (ConstantArray* ca = dyn_cast(cn)) { + if ( ca->isCString() ) { + name = ".objc_class_name_" + ca->getAsString(); + return true; + } + } + } + } + return false; +} + +// parse i386/ppc ObjC class data structure +void LTOModule::addObjCClass(GlobalVariable* clgv) +{ + if (ConstantStruct* c = dyn_cast(clgv->getInitializer())) { + // second slot in __OBJC,__class is pointer to superclass name + std::string superclassName; + if ( objcClassNameFromExpression(c->getOperand(1), superclassName) ) { + NameAndAttributes info; + if ( _undefines.find(superclassName.c_str()) == _undefines.end() ) { + const char* symbolName = ::strdup(superclassName.c_str()); + info.name = ::strdup(symbolName); + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + // string is owned by _undefines + _undefines[info.name] = info; + } + } + // third slot in __OBJC,__class is pointer to class name + std::string className; + if ( objcClassNameFromExpression(c->getOperand(2), className) ) { + const char* symbolName = ::strdup(className.c_str()); + NameAndAttributes info; + info.name = symbolName; + info.attributes = (lto_symbol_attributes) + (LTO_SYMBOL_PERMISSIONS_DATA | + LTO_SYMBOL_DEFINITION_REGULAR | + LTO_SYMBOL_SCOPE_DEFAULT); + _symbols.push_back(info); + _defines[info.name] = 1; + } + } +} + + +// parse i386/ppc ObjC category data structure +void LTOModule::addObjCCategory(GlobalVariable* clgv) +{ + if (ConstantStruct* c = dyn_cast(clgv->getInitializer())) { + // second slot in __OBJC,__category is pointer to target class name + std::string targetclassName; + if ( objcClassNameFromExpression(c->getOperand(1), targetclassName) ) { + NameAndAttributes info; + if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ){ + const char* symbolName = ::strdup(targetclassName.c_str()); + info.name = ::strdup(symbolName); + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + // string is owned by _undefines + _undefines[info.name] = info; + } + } + } +} + + +// parse i386/ppc ObjC class list data structure +void LTOModule::addObjCClassRef(GlobalVariable* clgv) +{ + std::string targetclassName; + if ( objcClassNameFromExpression(clgv->getInitializer(), targetclassName) ){ + NameAndAttributes info; + if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ) { + const char* symbolName = ::strdup(targetclassName.c_str()); + info.name = ::strdup(symbolName); + info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; + // string is owned by _undefines + _undefines[info.name] = info; + } + } +} + + +void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler) { // add to list of defined symbols addDefinedSymbol(v, mangler, false); + // special case i386/ppc ObjC data structures in magic sections + if ( v->hasSection() ) { + // special case if this data blob is an ObjC class definition + if ( v->getSection().compare(0, 15, "__OBJC,__class,") == 0 ) { + if (GlobalVariable* gv = dyn_cast(v)) { + addObjCClass(gv); + } + } + + // special case if this data blob is an ObjC category definition + else if ( v->getSection().compare(0, 18, "__OBJC,__category,") == 0 ) { + if (GlobalVariable* gv = dyn_cast(v)) { + addObjCCategory(gv); + } + } + + // special case if this data blob is the list of referenced classes + else if ( v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0 ) { + if (GlobalVariable* gv = dyn_cast(v)) { + addObjCClassRef(gv); + } + } + } + // add external symbols referenced by this data. for (unsigned count = 0, total = v->getNumOperands(); count != total; ++count) { @@ -192,9 +305,13 @@ void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler) void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler, bool isFunction) { + // ignore all llvm.* symbols + if ( strncmp(def->getNameStart(), "llvm.", 5) == 0 ) + return; + // string is owned by _defines const char* symbolName = ::strdup(mangler.getValueName(def).c_str()); - + // set alignment part log2() can have rounding errors uint32_t align = def->getAlignment(); uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0; @@ -241,25 +358,28 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler, } void LTOModule::addAsmGlobalSymbol(const char *name) { - // string is owned by _defines - const char *symbolName = ::strdup(name); - uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR; - attr |= LTO_SYMBOL_SCOPE_DEFAULT; - - // add to table of symbols - NameAndAttributes info; - info.name = symbolName; - info.attributes = (lto_symbol_attributes)attr; - _symbols.push_back(info); - _defines[info.name] = 1; + // only add new define if not already defined + if ( _defines.count(name, &name[strlen(name)+1]) == 0 ) + return; + + // string is owned by _defines + const char *symbolName = ::strdup(name); + uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR; + attr |= LTO_SYMBOL_SCOPE_DEFAULT; + NameAndAttributes info; + info.name = symbolName; + info.attributes = (lto_symbol_attributes)attr; + _symbols.push_back(info); + _defines[info.name] = 1; } void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler) { - const char* name = mangler.getValueName(decl).c_str(); // ignore all llvm.* symbols - if ( strncmp(name, "llvm.", 5) == 0 ) - return; + if ( strncmp(decl->getNameStart(), "llvm.", 5) == 0 ) + return; + + const char* name = mangler.getValueName(decl).c_str(); // we already have the symbol if (_undefines.find(name) != _undefines.end()) @@ -306,6 +426,14 @@ void LTOModule::lazyParseSymbols() // Use mangler to add GlobalPrefix to names to match linker names. Mangler mangler(*_module, _target->getTargetAsmInfo()->getGlobalPrefix()); + // add chars used in ObjC method names so method names aren't mangled + mangler.markCharAcceptable('['); + mangler.markCharAcceptable(']'); + mangler.markCharAcceptable('('); + mangler.markCharAcceptable(')'); + mangler.markCharAcceptable('-'); + mangler.markCharAcceptable('+'); + mangler.markCharAcceptable(' '); // add functions for (Module::iterator f = _module->begin(); f != _module->end(); ++f) { diff --git a/tools/lto/LTOModule.h b/tools/lto/LTOModule.h index bbda5ee0e2e..9de02a2a4e2 100644 --- a/tools/lto/LTOModule.h +++ b/tools/lto/LTOModule.h @@ -77,13 +77,19 @@ private: void addDefinedDataSymbol(llvm::GlobalValue* v, llvm::Mangler &mangler); void addAsmGlobalSymbol(const char *); + void addObjCClass(llvm::GlobalVariable* clgv); + void addObjCCategory(llvm::GlobalVariable* clgv); + void addObjCClassRef(llvm::GlobalVariable* clgv); + bool objcClassNameFromExpression(llvm::Constant* c, + std::string& name); + static bool isTargetMatch(llvm::MemoryBuffer* memBuffer, const char* triplePrefix); - + static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer, std::string& errMsg); static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length); - + typedef llvm::StringMap StringSet; struct NameAndAttributes {