ldc/gen/objcgen.cpp
2016-08-28 23:12:21 +02:00

160 lines
5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- objcgen.cpp -------------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
// Support limited to Objective-C on Darwin (OS X, iOS, tvOS, watchOS)
//
//===----------------------------------------------------------------------===//
#include "mtype.h"
#include "objc.h"
#include "gen/irstate.h"
#include "gen/objcgen.h"
namespace {
// Were any Objective-C symbols generated?
bool hasSymbols;
enum ABI {
none = 0,
fragile = 1,
nonFragile = 2
};
ABI abi = nonFragile;
// symbols that shouldn't be optimized away
std::vector<LLConstant *> retainedSymbols;
llvm::StringMap<LLGlobalVariable *> methVarNameMap;
llvm::StringMap<LLGlobalVariable *> methVarRefMap;
void retain(LLConstant *sym) {
retainedSymbols.push_back(DtoBitCast(sym, getVoidPtrType()));
}
void retainSymbols() {
// put all objc symbols in the llvm.compiler.used array so optimizer won't
// remove. Should do just once per module.
auto arrayType = LLArrayType::get(getVoidPtrType(), retainedSymbols.size());
auto usedArray = LLConstantArray::get(arrayType, retainedSymbols);
auto var = new LLGlobalVariable
(gIR->module, usedArray->getType(), false,
LLGlobalValue::AppendingLinkage,
usedArray,
"llvm.compiler.used");
var->setSection("llvm.metadata");
}
void genImageInfo() {
// Use LLVM to generate image info
const char *section = (abi == nonFragile ?
"__DATA,__objc_imageinfo,regular,no_dead_strip" :
"__OBJC,__image_info");
gIR->module.addModuleFlag(llvm::Module::Error,
"Objective-C Version", abi); // unused?
gIR->module.addModuleFlag(llvm::Module::Error,
"Objective-C Image Info Version", 0u); // version
gIR->module.addModuleFlag(llvm::Module::Error,
"Objective-C Image Info Section",
llvm::MDString::get(gIR->context(), section));
gIR->module.addModuleFlag(llvm::Module::Override,
"Objective-C Garbage Collection", 0u); // flags
}
LLGlobalVariable *getCStringVar(const char *symbol,
const llvm::StringRef &str,
const char *section) {
auto init = llvm::ConstantDataArray::getString(gIR->context(), str);
auto var = new LLGlobalVariable
(gIR->module, init->getType(), false,
LLGlobalValue::PrivateLinkage, init, symbol);
var->setSection(section);
return var;
}
LLGlobalVariable *getMethVarName(const llvm::StringRef &name) {
auto it = methVarNameMap.find(name);
if (it != methVarNameMap.end()) {
return it->second;
}
auto var = getCStringVar("OBJC_METH_VAR_NAME_", name,
abi == nonFragile ?
"__TEXT,__objc_methname,cstring_literals" :
"__TEXT,__cstring,cstring_literals");
methVarNameMap[name] = var;
retain(var);
return var;
}
} // end local stuff
bool objc_isSupported(const llvm::Triple &triple) {
if (triple.isOSDarwin()) {
// Objective-C only supported on Darwin at this time
switch (triple.getArch()) {
#if LDC_LLVM_VER == 305
case llvm::Triple::arm64:
#endif
case llvm::Triple::aarch64: // arm64 iOS, tvOS
case llvm::Triple::arm: // armv6 iOS
case llvm::Triple::thumb: // thumbv7 iOS, watchOS
case llvm::Triple::x86_64: // OSX, iOS, tvOS sim
abi = nonFragile;
return true;
case llvm::Triple::x86: // OSX, iOS, watchOS sim
abi = fragile;
return true;
default:
break;
}
}
return false;
}
// called by ddmd.objc.objc_tryMain_init()
void objc_initSymbols() {
hasSymbols = false;
retainedSymbols.clear();
methVarNameMap.clear();
methVarRefMap.clear();
}
LLGlobalVariable *objc_getMethVarRef(const ObjcSelector &sel) {
llvm::StringRef s(sel.stringvalue, sel.stringlen);
auto it = methVarRefMap.find(s);
if (it != methVarRefMap.end()) {
return it->second;
}
auto gvar = getMethVarName(s);
auto selref = new LLGlobalVariable
(gIR->module, gvar->getType(),
false, // prevent const elimination optimization
LLGlobalValue::PrivateLinkage,
gvar,
"OBJC_SELECTOR_REFERENCES_",
nullptr, LLGlobalVariable::NotThreadLocal, 0,
true); // externally initialized
selref->setSection(abi == nonFragile ?
"__DATA,__objc_selrefs,literal_pointers,no_dead_strip" :
"__OBJC,__message_refs,literal_pointers,no_dead_strip");
// Save for later lookup and prevent optimizer elimination
methVarRefMap[s] = selref;
retain(selref);
hasSymbols = true;
return selref;
}
void objc_Module_genmoduleinfo_classes() {
if (hasSymbols) {
genImageInfo();
// add in references so optimizer won't remove symbols.
retainSymbols();
}
}