Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 1e557ba

Browse files
committed
[WebAssembly] Prevent inline assembly from being mangled by SjLj
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364985 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e7cfaf6 commit 1e557ba

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,13 @@ bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M,
485485
if (CalleeF->isIntrinsic())
486486
return false;
487487

488+
// Attempting to transform inline assembly will result in something like:
489+
// call void @__invoke_void(void ()* asm ...)
490+
// which is invalid because inline assembly blocks do not have addresses
491+
// and can't be passed by pointer. The result is a crash with illegal IR.
492+
if (isa<InlineAsm>(Callee))
493+
return false;
494+
488495
// The reason we include malloc/free here is to exclude the malloc/free
489496
// calls generated in setjmp prep / cleanup routines.
490497
Function *SetjmpF = M.getFunction("setjmp");

test/CodeGen/WebAssembly/lower-em-sjlj.ll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,27 @@ entry:
188188
; CHECK-NEXT: call void @emscripten_longjmp_jmpbuf(%struct.__jmp_buf_tag* %[[ARRAYDECAY]], i32 5) #1
189189
}
190190

191+
; Test inline asm handling
192+
define hidden void @inline_asm() #0 {
193+
; CHECK-LABEL: @inline_asm
194+
entry:
195+
%env = alloca [1 x %struct.__jmp_buf_tag], align 16
196+
%arraydecay = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %env, i32 0, i32 0
197+
%call = call i32 @setjmp(%struct.__jmp_buf_tag* %arraydecay) #4
198+
%cmp = icmp eq i32 %call, 0
199+
br i1 %cmp, label %if.then, label %if.else
200+
201+
if.then: ; preds = %entry
202+
; CHECK: call void asm sideeffect "", ""()
203+
call void asm sideeffect "", ""()
204+
%arraydecay1 = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %env, i32 0, i32 0
205+
call void @longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 1) #5
206+
unreachable
207+
208+
if.else: ; preds = %entry
209+
ret void
210+
}
211+
191212
declare void @foo()
192213
; Function Attrs: returns_twice
193214
declare i32 @setjmp(%struct.__jmp_buf_tag*) #0

0 commit comments

Comments
 (0)