diff --git a/include/swift/IRGen/Options.h b/include/swift/IRGen/Options.h index bf218a2a739..c1f7d3889a3 100644 --- a/include/swift/IRGen/Options.h +++ b/include/swift/IRGen/Options.h @@ -56,7 +56,11 @@ public: /// The optimization level, as in -O2. unsigned OptLevel : 2; - Options() : OutputKind(OutputKind::LLVMAssembly), Verify(true), OptLevel(0) {} + /// \brief Whether we're generating IR for the JIT. + unsigned UseJIT : 1; + + Options() : OutputKind(OutputKind::LLVMAssembly), Verify(true), OptLevel(0), + UseJIT(false) {} }; } // end namespace irgen diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp index 686b5592f62..ac2259c467c 100644 --- a/lib/IRGen/GenObjC.cpp +++ b/lib/IRGen/GenObjC.cpp @@ -18,6 +18,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Module.h" +#include "swift/IRGen/Options.h" #include "swift/AST/Decl.h" #include "swift/AST/Types.h" @@ -68,6 +69,17 @@ llvm::Constant *IRGenModule::getObjCMsgSendStretFn() { return ObjCMsgSendStretFn; } +llvm::Constant *IRGenModule::getObjCSelRegisterNameFn() { + if (ObjCSelRegisterNameFn) return ObjCSelRegisterNameFn; + + // SEL sel_registerName(const char *str); + llvm::Type *argTypes[1] = { Int8PtrTy }; + auto fnType = llvm::FunctionType::get(Int8PtrTy, argTypes, false); + ObjCSelRegisterNameFn = createObjCRuntimeFunction(*this, "sel_registerName", + fnType); + return ObjCSelRegisterNameFn; +} + #define DEFINE_OBJC_RUNTIME_FUNCTION(LABEL, NAME, RETTY) \ llvm::Constant *IRGenModule::getObjC##LABEL##Fn() { \ if (ObjC##LABEL##Fn) return ObjC##LABEL##Fn; \ @@ -418,10 +430,24 @@ CallEmission irgen::prepareObjCMethodCall(IRGenFunction &IGF, FuncDecl *method, selfValues.addUnmanaged(value.getValue()); // Add the selector value. + llvm::Value *selectorV; Selector selector(method); - auto selectorRef = IGF.IGM.getAddrOfObjCSelectorRef(selector.str()); - auto selectorV = - IGF.Builder.CreateLoad(Address(selectorRef, IGF.IGM.getPointerAlignment())); + if (IGF.IGM.Opts.UseJIT) { + // When generating JIT'd code, we need to call sel_registerName() to force + // the runtime to unique the selector. + auto selectorRef = IGF.IGM.getAddrOfObjCSelectorRef(selector.str()); + selectorV = IGF.Builder.CreateLoad(Address(selectorRef, + IGF.IGM.getPointerAlignment())); + selectorV = IGF.Builder.CreateCall(IGF.IGM.getObjCSelRegisterNameFn(), + selectorV); + } else { + // When generating statically-compiled code, just build a reference to + // the selector. + auto selectorRef = IGF.IGM.getAddrOfObjCSelectorRef(selector.str()); + selectorV = IGF.Builder.CreateLoad(Address(selectorRef, + IGF.IGM.getPointerAlignment())); + } + selfValues.addUnmanaged(selectorV); // Add that to the emission. diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 0c21fd9f9f2..ae37657db40 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -208,6 +208,8 @@ public: llvm::Constant *getObjCMsgSendFn(); llvm::Constant *getObjCMsgSendStretFn(); + llvm::Constant *getObjCSelRegisterNameFn(); + llvm::Constant *getGetFunctionMetadataFn(); llvm::Constant *getGetGenericMetadataFn(); llvm::Constant *getGetMetatypeMetadataFn(); @@ -232,6 +234,7 @@ private: llvm::Constant *ObjCReleaseFn = nullptr; llvm::Constant *ObjCMsgSendFn = nullptr; llvm::Constant *ObjCMsgSendStretFn = nullptr; + llvm::Constant *ObjCSelRegisterNameFn = nullptr; //--- Generic --------------------------------------------------------------- public: diff --git a/tools/swift/Immediate.cpp b/tools/swift/Immediate.cpp index bb3f8e0fc41..1ef32e8597a 100644 --- a/tools/swift/Immediate.cpp +++ b/tools/swift/Immediate.cpp @@ -143,7 +143,8 @@ void swift::RunImmediately(TranslationUnit *TU) { Options.Triple = llvm::sys::getDefaultTargetTriple(); Options.OptLevel = 2; Options.OutputKind = irgen::OutputKind::Module; - + Options.UseJIT = true; + // IRGen the main module. llvm::LLVMContext LLVMContext; llvm::Module Module(TU->Name.str(), LLVMContext); @@ -299,7 +300,8 @@ void swift::REPL(ASTContext &Context) { Options.Triple = llvm::sys::getDefaultTargetTriple(); Options.OptLevel = 0; Options.OutputKind = irgen::OutputKind::Module; - + Options.UseJIT = true; + EditLineWrapper e; char* CurBuffer = const_cast(Buffer->getBufferStart());