[arm] set exception handling model to dwarf for iOS
authorBernhard Urban <lewurm@gmail.com>
Fri, 21 Jun 2019 14:26:24 +0000 (16:26 +0200)
committerMarek Safar <marek.safar@gmail.com>
Mon, 24 Jun 2019 07:48:45 +0000 (09:48 +0200)
We recently switched the AOT compiler for iOS armv7 from 32bit host to 64bit host. At the same time we _also_ switched from LLVM 3.6 to the newer LLVM 6.0 fork we support.

In a Xamarin.iOS Release build for iOS armv7 exception handling would crash. Specifically the problem was that the exception object wasn't properly injected into the handler block. The way it works is, that the exception handler machinery passes the pointer to the exception object via `r0`.

With the newer LLVM the generated code of the exception handling block
looks like this:
```
LBB1_15:                                @ %EH_CLAUSE0_BB3
Ltmp8:
ldr r0, [sp, mono/mono#24]
str r0, [sp, mono/mono#4]
ldr r0, [sp, mono/mono#28]
ldr r0, [sp, mono/mono#12]
ldr r0, [r0]
cmp r0, mono/mono#0
beq LBB1_17
```
thus overwriting `r0`, so that the pointer to the exception object is lost.  With the older LLVM 3.6 the generated code looks like this:
```
LBB1_8:                                 @ %EH_CLAUSE0_BB3
Ltmp8:
str r0, [sp, mono/mono#4]
ldr r0, [r6]
cmp r0, mono/mono#0
beq LBB1_10
```
correctly storing the exception object into a stack slot for later usage.

After some time I figured out that there are _different_ exception handling models. Depending on the model, the exception pointer is passed in `r0` or not:
https://github.com/mono/llvm/blob/mono/mono@2bd2f1db1803f7b36687e5abf912c69baa848305/lib/Target/ARM/ARMISelLowering.cpp#L14416-L14428

`SjLj` stands for "SetJump / LongJump" and  means that exception handling is implemented with this. On iOS this is the default model that is used. We want `dwarf` instead, so we tell this `llc` now and the generated code handles it correctly.

So why was it working before? In our older LLVM 3.6 fork we hardcoded it:
https://github.com/mono/llvm/blob/mono/mono@f80899cb3eb75f7f5640b4519e83bd96991bffb8/lib/Target/ARM/ARMISelLowering.cpp#L756-L762

The `-exception-model=` option is also not available in LLVM 3.6.

Contributes to https://github.com/mono/mono/issues/15058 and https://github.com/mono/mono/issues/9621

Commit migrated from https://github.com/mono/mono/commit/7d5daa2f77246a036f19ddb34ac4715c5ca58f36

src/mono/mono/mini/aot-compiler.c

index a6bca65..931e54d 100644 (file)
@@ -1123,8 +1123,12 @@ arch_init (MonoAotCompile *acfg)
                if (!(acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "thumb")))
                        g_string_append (acfg->llc_args, " -march=arm");
 
-               if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "ios"))
+               if (acfg->aot_opts.mtriple && strstr (acfg->aot_opts.mtriple, "ios")) {
                        g_string_append (acfg->llc_args, " -mattr=+v7");
+#ifdef LLVM_API_VERSION > 100
+                       g_string_append (acfg->llc_args, " -exception-model=dwarf");
+#endif
+               }
 
 #if defined(ARM_FPU_VFP_HARD)
                g_string_append (acfg->llc_args, " -mattr=+vfp2,-neon,+d16 -float-abi=hard");