[llvm] Fix intrinsic Selector.GetHandle support. (#4103)
authorRolf Bjarne Kvinge <rolf@xamarin.com>
Tue, 6 Dec 2016 23:50:31 +0000 (00:50 +0100)
committerZoltan Varga <vargaz@gmail.com>
Tue, 6 Dec 2016 23:50:31 +0000 (18:50 -0500)
An OBJC_IMAGE_INFO section must be emitted when we emit the native equivalent
of @selector for Selector.GetHandle, otherwise the Objective-C runtime will
not process the selectors in this image at runtime (and we may end up with
duplicate selectors in memory).

The AOT compiler already does this here: https://github.com/mono/mono/blob/2eda626316fd8f70cd98947af2f89b7ca9b0ebe5/mono/mini/aot-compiler.c#L9657-L9661

mono/mini/mini-llvm.c

index ab6d21f92c5b40f7a7a84ea82daeed2c35051926..aac470915ef0fae8057cef9ff3775ccef36d2537 100644 (file)
@@ -5871,8 +5871,19 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        const char *name = (const char*)ins->inst_p0;
                        LLVMValueRef var;
 
-                       if (!ctx->module->objc_selector_to_var)
+                       if (!ctx->module->objc_selector_to_var) {
                                ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+                               LLVMValueRef info_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), 8), "@OBJC_IMAGE_INFO");
+                               int32_t objc_imageinfo [] = { 0, 16 };
+                               LLVMSetInitializer (info_var, mono_llvm_create_constant_data_array ((uint8_t *) &objc_imageinfo, 8));
+                               LLVMSetLinkage (info_var, LLVMPrivateLinkage);
+                               LLVMSetExternallyInitialized (info_var, TRUE);
+                               LLVMSetSection (info_var, "__DATA, __objc_imageinfo,regular,no_dead_strip");
+                               LLVMSetAlignment (info_var, sizeof (mgreg_t));
+                               mark_as_used (ctx->module, info_var);
+                       }
+
                        var = g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
                        if (!var) {
                                LLVMValueRef indexes [16];