Skip to content

Commit

Permalink
[WebAssembly] Prevent inline assembly from being mangled by SjLj
Browse files Browse the repository at this point in the history
Summary:
Before, inline assembly gets mangled by the SjLj transformation.

For example, in a function with setjmp/longjmp, this LLVM IR code

    call void asm sideeffect "", ""()

would be transformed into

    call void @__invoke_void(void ()* asm sideeffect "", "")

This is invalid, and results in the error:

    Cannot take the address of an inline asm!

In this diff, we skip the transformation for inline assembly.

Reviewers: aheejin, tlively

Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D64115

llvm-svn: 364985
  • Loading branch information
quantum5 committed Jul 3, 2019
1 parent 4f3472d commit b88ebe8
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,13 @@ bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M,
if (CalleeF->isIntrinsic())
return false;

// Attempting to transform inline assembly will result in something like:
// call void @__invoke_void(void ()* asm ...)
// which is invalid because inline assembly blocks do not have addresses
// and can't be passed by pointer. The result is a crash with illegal IR.
if (isa<InlineAsm>(Callee))
return false;

// The reason we include malloc/free here is to exclude the malloc/free
// calls generated in setjmp prep / cleanup routines.
Function *SetjmpF = M.getFunction("setjmp");
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,27 @@ entry:
; CHECK-NEXT: call void @emscripten_longjmp_jmpbuf(%struct.__jmp_buf_tag* %[[ARRAYDECAY]], i32 5) #1
}

; Test inline asm handling
define hidden void @inline_asm() #0 {
; CHECK-LABEL: @inline_asm
entry:
%env = alloca [1 x %struct.__jmp_buf_tag], align 16
%arraydecay = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %env, i32 0, i32 0
%call = call i32 @setjmp(%struct.__jmp_buf_tag* %arraydecay) #4
%cmp = icmp eq i32 %call, 0
br i1 %cmp, label %if.then, label %if.else

if.then: ; preds = %entry
; CHECK: call void asm sideeffect "", ""()
call void asm sideeffect "", ""()
%arraydecay1 = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %env, i32 0, i32 0
call void @longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 1) #5
unreachable

if.else: ; preds = %entry
ret void
}

declare void @foo()
; Function Attrs: returns_twice
declare i32 @setjmp(%struct.__jmp_buf_tag*) #0
Expand Down

0 comments on commit b88ebe8

Please sign in to comment.