llvm.localsescape/recover

I 'm using locals recover to have a seh finally in a separate function:

  %1 = alloca i8*, align 4
  store i8* %0, i8** %1
  %2 = alloca i32
  store i32 0, i32* %2
call void (...) @llvm.localescape(i8** %1, i32* %2)

call my finaly like:

  %loctmp = call i8* @llvm.localaddress()
call void @"TEST$Fin0"(i8 0, i8* %loctmp)

and recover it with:

%2 = call i8* @llvm.localrecover(i8* bitcast (void (i8*)* @TEST to i8*), i8* %1, i32 0)
  %3 = bitcast i8* %2 to i8**
%4 = load i8*, i8** %3

I get the right value passed to my original function (ie %1)

If I however *just* add a struct with 3 doubles alloca in it and localsescape those too:
  
  %3 = alloca %threedoubles
store %threedoubles zeroinitializer, %threedoubles* %3
call void (...) @llvm.localescape(i8** %1, i32* %2, %threedoubles* %3)

I get a different value (full testcase here)

https://gist.github.com/carlokok/e1c9aef9c8a382afdb280385a422f913

What am I doing wrong here?

I would guess that %threedoubles has a large alignment and that is making things go wrong. I thought we fixed this bug, though. I can’t find it in the tracker, but it’s in there. Someone used __try with local variables of type ‘double’ on 32-bit and things didn’t work out. I’m pretty sure we fixed it though.

That's quite likely. I can reproduce this issue with llvm 6.0 though. I'll try with svn HEAD.

Shows with HEAD. I can't find anything in bugzilla related to this either.

This pattern does work:

%1 = alloca <{ %Program**, %ThreeStructs* }>
  %15 = getelementptr <{ %Program**, i32*, %ThreeStructs* }>, <{ %Program**, %ThreeStructs* }>* %1, i32 0, i32 0, !dbg !62
  store %Program** %2, %Program*** %15, !dbg !62
%17 = getelementptr <{ %Program**, i32*, %ThreeStructs* }>, <{ %Program**, %ThreeStructs* }>* %1, i32 0, i32 1, !dbg !62
  store %ThreeStructs* %4, %ThreeStructs** %17, !dbg !62

...cleanuppad:
%28 = bitcast <{ %Program**, %ThreeStructs* }>* %1 to i8*, !dbg !68
  call void @"mi_t1d_ConsoleApplication2_d_Program4_Test$Fin0"(i8 1, i8* %28) [ "funclet"(token %27) ], !dbg !68
...non eh cleanup:
%30 = bitcast <{ %Program**, %ThreeStructs* }>* %1 to i8*, !dbg !67
  call void @"mi_t1d_ConsoleApplication2_d_Program4_Test$Fin0"(i8 1, i8* %30), !dbg !67
    
define void @"mi_t1d_ConsoleApplication2_d_Program4_Test$Fin0"(i8, i8*) #3 comdat {
BasicBlock8:
  %2 = bitcast i8* %1 to <{ %Program**, i32*, %ThreeStructs* }>*, !dbg !68
  %3 = getelementptr <{ %Program**, i32*, %ThreeStructs* }>, <{ %Program**, i32*, %ThreeStructs* }>* %2, i32 0, i32 0, !dbg !68
  %4 = load %Program**, %Program*** %3, !dbg !68

So it's really the localsescape/restore that doesn't. I can work with this (though odds are it doesn't optimize as well) for now.