Skip to content

Commit

Permalink
Merge pull request #2389 from kinke/objc
Browse files Browse the repository at this point in the history
Objective-C fixes
  • Loading branch information
kinke committed Oct 28, 2017
2 parents aeaf35c + 95915a8 commit 8f4027f
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 128 deletions.
2 changes: 1 addition & 1 deletion ddmd/gluelayer.d
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ version (IN_LLVM)
{
Statement asmSemantic(AsmStatement s, Scope* sc);
RET retStyle(TypeFunction tf);
void objc_initSymbols(); // in gen/objcgen.cpp
void objc_initSymbols() {}
}
}
else version (NoBackend)
Expand Down
2 changes: 2 additions & 0 deletions driver/codegenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ void CodeGenerator::finishLLModule(Module *m) {
}

void CodeGenerator::writeAndFreeLLModule(const char *filename) {
ir_->objc.finalize();

// Issue #1829: make sure all replaced global variables are replaced
// everywhere.
ir_->replaceGlobals();
Expand Down
3 changes: 3 additions & 0 deletions gen/abi-x86-64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction *tf, IrFuncTy &fty) {
if (fty.arg_this || fty.arg_nest) {
regCount.int_regs--;
}
if (fty.arg_objcSelector) {
regCount.int_regs--;
}
if (fty.arg_arguments) {
regCount.int_regs -= 2; // dynamic array
}
Expand Down
12 changes: 5 additions & 7 deletions gen/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,19 +632,17 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
++iarg;
}

// TODO: do we need this?
if (irFty.arg_objcSelector) {
iarg->setName(".objcSelector_arg");
irFunc->thisArg = &(*iarg);
++iarg;
}

if (passThisBeforeSret) {
iarg->setName(".sret_arg");
irFunc->sretArg = &(*iarg);
++iarg;
}

if (irFty.arg_objcSelector) {
iarg->setName(".objcSelector_arg");
++iarg;
}

if (irFty.arg_arguments) {
iarg->setName("._arguments");
irFunc->_arguments = &(*iarg);
Expand Down
2 changes: 1 addition & 1 deletion gen/irstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ IRScope &IRScope::operator=(const IRScope &rhs) {

////////////////////////////////////////////////////////////////////////////////
IRState::IRState(const char *name, llvm::LLVMContext &context)
: module(name, context), DBuilder(this) {
: module(name, context), DBuilder(this), objc(module) {
ir.state = this;
}

Expand Down
5 changes: 4 additions & 1 deletion gen/irstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "aggregate.h"
#include "root.h"
#include "gen/dibuilder.h"
#include "gen/objcgen.h"
#include "ir/iraggr.h"
#include "ir/irvar.h"
#include "llvm/ADT/StringMap.h"
Expand Down Expand Up @@ -105,7 +106,7 @@ struct IRAsmBlock {
retfixup(nullptr) {}
};

// represents the module
// represents the LLVM module (object file)
struct IRState {
private:
std::vector<std::pair<llvm::GlobalVariable *, llvm::Constant *>>
Expand All @@ -125,6 +126,8 @@ struct IRState {

LLStructType *moduleRefType = nullptr;

ObjCState objc;

// Stack of currently codegen'd functions (more than one for lambdas or other
// nested functions, inlining-only codegen'ing, etc.), and some convenience
// accessors for the top-most one.
Expand Down
3 changes: 0 additions & 3 deletions gen/moduleinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "gen/llvmhelpers.h"
#include "gen/logger.h"
#include "gen/mangling.h"
#include "gen/objcgen.h"
#include "gen/rttibuilder.h"
#include "ir/irfunction.h"
#include "ir/irmodule.h"
Expand Down Expand Up @@ -306,8 +305,6 @@ llvm::GlobalVariable *genModuleInfo(Module *m) {
const auto at = llvm::ArrayType::get(it, len);
b.push(toConstantArray(it, at, name, len, false));

objc_Module_genmoduleinfo_classes();

// Create a global symbol with the above initialiser.
LLGlobalVariable *moduleInfoSym = getIrModule(m)->moduleInfoSymbol();
b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym);
Expand Down
175 changes: 74 additions & 101 deletions gen/objcgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,100 +9,27 @@
//
//===----------------------------------------------------------------------===//

#include "gen/objcgen.h"
#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
};

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()) {
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
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
case llvm::Triple::x86: // OSX, iOS, watchOS sim
abi = fragile;
return true;
default:
Expand All @@ -112,46 +39,92 @@ bool objc_isSupported(const llvm::Triple &triple) {
return false;
}

// called by the ddmd.objc.Supported ctor
void objc_initSymbols() {
hasSymbols = false;
retainedSymbols.clear();
methVarNameMap.clear();
methVarRefMap.clear();
LLGlobalVariable *ObjCState::getCStringVar(const char *symbol,
const llvm::StringRef &str,
const char *section) {
auto init = llvm::ConstantDataArray::getString(module.getContext(), str);
auto var = new LLGlobalVariable(module, init->getType(), false,
LLGlobalValue::PrivateLinkage, init, symbol);
var->setSection(section);
return var;
}

LLGlobalVariable *objc_getMethVarRef(const ObjcSelector &sel) {
LLGlobalVariable *ObjCState::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;
}

LLGlobalVariable *ObjCState::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");
auto selref = new LLGlobalVariable(
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) {
void ObjCState::retain(LLConstant *sym) {
retainedSymbols.push_back(DtoBitCast(sym, getVoidPtrType()));
}

void ObjCState::finalize() {
if (!retainedSymbols.empty()) {
genImageInfo();
// add in references so optimizer won't remove symbols.
retainSymbols();
}
}

void ObjCState::genImageInfo() {
// Use LLVM to generate image info
const char *section =
(abi == nonFragile ? "__DATA,__objc_imageinfo,regular,no_dead_strip"
: "__OBJC,__image_info");
module.addModuleFlag(llvm::Module::Error, "Objective-C Version",
abi); // unused?
module.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
0u); // version
module.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
llvm::MDString::get(module.getContext(), section));
module.addModuleFlag(llvm::Module::Override, "Objective-C Garbage Collection",
0u); // flags
}

void ObjCState::retainSymbols() {
// put all objc symbols in the llvm.compiler.used array so optimizer won't
// remove.
auto arrayType = LLArrayType::get(retainedSymbols.front()->getType(),
retainedSymbols.size());
auto usedArray = LLConstantArray::get(arrayType, retainedSymbols);
auto var = new LLGlobalVariable(module, arrayType, false,
LLGlobalValue::AppendingLinkage, usedArray,
"llvm.compiler.used");
var->setSection("llvm.metadata");
}
35 changes: 32 additions & 3 deletions gen/objcgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,44 @@
#ifndef LDC_GEN_OBJCGEN_H
#define LDC_GEN_OBJCGEN_H

#include <vector>
#include "llvm/ADT/StringMap.h"

struct ObjcSelector;
namespace llvm {
class Constant;
class GlobalVariable;
class Module;
class Triple;
}

bool objc_isSupported(const llvm::Triple &triple);
void objc_initSymbols();
void objc_Module_genmoduleinfo_classes();
llvm::GlobalVariable *objc_getMethVarRef(const ObjcSelector &sel);

// Objective-C state tied to an LLVM module (object file).
class ObjCState {
public:
ObjCState(llvm::Module &module) : module(module) {}

llvm::GlobalVariable *getMethVarRef(const ObjcSelector &sel);
void finalize();

private:
llvm::Module &module;

// symbols that shouldn't be optimized away
std::vector<llvm::Constant *> retainedSymbols;

llvm::StringMap<llvm::GlobalVariable *> methVarNameMap;
llvm::StringMap<llvm::GlobalVariable *> methVarRefMap;

llvm::GlobalVariable *getCStringVar(const char *symbol,
const llvm::StringRef &str,
const char *section);
llvm::GlobalVariable *getMethVarName(const llvm::StringRef &name);
void retain(llvm::Constant *sym);

void genImageInfo();
void retainSymbols();
};

#endif // LDC_GEN_OBJCGEN_H
Loading

0 comments on commit 8f4027f

Please sign in to comment.