Skip to content

Commit d10ce97

Browse files
committed
[WebAssembly] Stop generating helper functions in WebAssemblyLowerEmscriptenEHSjLj
Previously we were creating weakly defined helper function in each translation unit: - setThrew - setTempRet0 Instead we now assume these will be provided at link time. In emscripten they are provided in compiler-rt: emscripten-core/emscripten#7203 Additionally we previously created three global variable which are also now required to exist at link time instead. - __THREW__ - _threwValue - __tempRet0 Differential Revision: https://reviews.llvm.org/D49208 llvm-svn=343640
1 parent 2276e2f commit d10ce97

File tree

3 files changed

+23
-112
lines changed

3 files changed

+23
-112
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp

Lines changed: 17 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
///
5151
/// In detail, this pass does following things:
5252
///
53-
/// 1) Create three global variables: __THREW__, __threwValue, and __tempRet0.
53+
/// 1) Assumes the existence of global variables: __THREW__, __threwValue, and
54+
/// __tempRet0.
5455
/// __tempRet0 will be set within __cxa_find_matching_catch() function in
5556
/// JS library, and __THREW__ and __threwValue will be set in invoke wrappers
5657
/// in JS glue code. For what invoke wrappers are, refer to 3). These
@@ -65,9 +66,10 @@
6566
///
6667
/// * Exception handling
6768
///
68-
/// 2) Create setThrew and setTempRet0 functions.
69-
/// The global variables created in 1) will exist in wasm address space,
70-
/// but their values should be set in JS code, so we provide these functions
69+
/// 2) We assume the existence of setThrew and setTempRet0 functions at link
70+
/// time.
71+
/// The global variables in 1) will exist in wasm address space,
72+
/// but their values should be set in JS code, so these functions
7173
/// as interfaces to JS glue code. These functions are equivalent to the
7274
/// following JS functions, which actually exist in asm.js version of JS
7375
/// library.
@@ -272,9 +274,6 @@ class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass {
272274
bool areAllExceptionsAllowed() const { return EHWhitelistSet.empty(); }
273275
bool canLongjmp(Module &M, const Value *Callee) const;
274276

275-
void createSetThrewFunction(Module &M);
276-
void createSetTempRet0Function(Module &M);
277-
278277
void rebuildSSA(Function &F);
279278

280279
public:
@@ -333,13 +332,15 @@ static bool canThrow(const Value *V) {
333332
return true;
334333
}
335334

336-
static GlobalVariable *createGlobalVariableI32(Module &M, IRBuilder<> &IRB,
337-
const char *Name) {
335+
// Get a global variable with the given name. If it doesn't exist declare it,
336+
// which will generate an import and asssumes that it will exist at link time.
337+
static GlobalVariable *getGlobalVariableI32(Module &M, IRBuilder<> &IRB,
338+
const char *Name) {
338339
if (M.getNamedGlobal(Name))
339340
report_fatal_error(Twine("variable name is reserved: ") + Name);
340341

341342
return new GlobalVariable(M, IRB.getInt32Ty(), false,
342-
GlobalValue::WeakODRLinkage, IRB.getInt32(0), Name);
343+
GlobalValue::ExternalLinkage, nullptr, Name);
343344
}
344345

345346
// Simple function name mangler.
@@ -590,67 +591,6 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
590591
LongjmpResult = IRB.CreateLoad(TempRet0GV, "longjmp_result");
591592
}
592593

593-
// Create setThrew function
594-
// function setThrew(threw, value) {
595-
// if (__THREW__ == 0) {
596-
// __THREW__ = threw;
597-
// __threwValue = value;
598-
// }
599-
// }
600-
void WebAssemblyLowerEmscriptenEHSjLj::createSetThrewFunction(Module &M) {
601-
LLVMContext &C = M.getContext();
602-
IRBuilder<> IRB(C);
603-
604-
if (M.getNamedGlobal("setThrew"))
605-
report_fatal_error("setThrew already exists");
606-
607-
Type *Params[] = {IRB.getInt32Ty(), IRB.getInt32Ty()};
608-
FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false);
609-
Function *F =
610-
Function::Create(FTy, GlobalValue::WeakODRLinkage, "setThrew", &M);
611-
Argument *Arg1 = &*(F->arg_begin());
612-
Argument *Arg2 = &*std::next(F->arg_begin());
613-
Arg1->setName("threw");
614-
Arg2->setName("value");
615-
BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
616-
BasicBlock *ThenBB = BasicBlock::Create(C, "if.then", F);
617-
BasicBlock *EndBB = BasicBlock::Create(C, "if.end", F);
618-
619-
IRB.SetInsertPoint(EntryBB);
620-
Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val");
621-
Value *Cmp = IRB.CreateICmpEQ(Threw, IRB.getInt32(0), "cmp");
622-
IRB.CreateCondBr(Cmp, ThenBB, EndBB);
623-
624-
IRB.SetInsertPoint(ThenBB);
625-
IRB.CreateStore(Arg1, ThrewGV);
626-
IRB.CreateStore(Arg2, ThrewValueGV);
627-
IRB.CreateBr(EndBB);
628-
629-
IRB.SetInsertPoint(EndBB);
630-
IRB.CreateRetVoid();
631-
}
632-
633-
// Create setTempRet0 function
634-
// function setTempRet0(value) {
635-
// __tempRet0 = value;
636-
// }
637-
void WebAssemblyLowerEmscriptenEHSjLj::createSetTempRet0Function(Module &M) {
638-
LLVMContext &C = M.getContext();
639-
IRBuilder<> IRB(C);
640-
641-
if (M.getNamedGlobal("setTempRet0"))
642-
report_fatal_error("setTempRet0 already exists");
643-
Type *Params[] = {IRB.getInt32Ty()};
644-
FunctionType *FTy = FunctionType::get(IRB.getVoidTy(), Params, false);
645-
Function *F =
646-
Function::Create(FTy, GlobalValue::WeakODRLinkage, "setTempRet0", &M);
647-
F->arg_begin()->setName("value");
648-
BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F);
649-
IRB.SetInsertPoint(EntryBB);
650-
IRB.CreateStore(&*F->arg_begin(), TempRet0GV);
651-
IRB.CreateRetVoid();
652-
}
653-
654594
void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) {
655595
DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
656596
DT.recalculate(F); // CFG has been changed
@@ -688,11 +628,12 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
688628
bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty();
689629
bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed);
690630

691-
// Create global variables __THREW__, threwValue, and __tempRet0, which are
692-
// used in common for both exception handling and setjmp/longjmp handling
693-
ThrewGV = createGlobalVariableI32(M, IRB, "__THREW__");
694-
ThrewValueGV = createGlobalVariableI32(M, IRB, "__threwValue");
695-
TempRet0GV = createGlobalVariableI32(M, IRB, "__tempRet0");
631+
// Declare (or get) global variables __THREW__, __threwValue, and __tempRet0,
632+
// which are used in common for both exception handling and setjmp/longjmp
633+
// handling
634+
ThrewGV = getGlobalVariableI32(M, IRB, "__THREW__");
635+
ThrewValueGV = getGlobalVariableI32(M, IRB, "__threwValue");
636+
TempRet0GV = getGlobalVariableI32(M, IRB, "__tempRet0");
696637

697638
bool Changed = false;
698639

@@ -764,9 +705,6 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
764705

765706
if (!Changed) {
766707
// Delete unused global variables and functions
767-
ThrewGV->eraseFromParent();
768-
ThrewValueGV->eraseFromParent();
769-
TempRet0GV->eraseFromParent();
770708
if (ResumeF)
771709
ResumeF->eraseFromParent();
772710
if (EHTypeIDF)
@@ -780,12 +718,6 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
780718
return false;
781719
}
782720

783-
// If we have made any changes while doing exception handling or
784-
// setjmp/longjmp handling, we have to create these functions for JavaScript
785-
// to call.
786-
createSetThrewFunction(M);
787-
createSetTempRet0Function(M);
788-
789721
return true;
790722
}
791723

llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ target triple = "wasm32-unknown-unknown"
55

66
@_ZTIi = external constant i8*
77
@_ZTIc = external constant i8*
8-
; CHECK-DAG: __THREW__ = weak_odr global i32 0
9-
; CHECK-DAG: __threwValue = weak_odr global i32 0
10-
; CHECK-DAG: __tempRet0 = weak_odr global i32 0
8+
; CHECK-DAG: __THREW__ = external global i32
9+
; CHECK-DAG: __threwValue = external global i32
10+
; CHECK-DAG: __tempRet0 = external global i32
1111

1212
; Test invoke instruction with clauses (try-catch block)
1313
define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
@@ -171,24 +171,3 @@ declare void @__cxa_call_unexpected(i8*)
171171
; CHECK-DAG: declare void @__resumeException(i8*)
172172
; CHECK-DAG: declare void @__invoke_void_i32(void (i32)*, i32)
173173
; CHECK-DAG: declare i8* @__cxa_find_matching_catch_4(i8*, i8*)
174-
175-
; setThrew function creation
176-
; CHECK-LABEL: define weak_odr void @setThrew(i32 %threw, i32 %value) {
177-
; CHECK: entry:
178-
; CHECK-NEXT: %__THREW__.val = load i32, i32* @__THREW__
179-
; CHECK-NEXT: %cmp = icmp eq i32 %__THREW__.val, 0
180-
; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
181-
; CHECK: if.then:
182-
; CHECK-NEXT: store i32 %threw, i32* @__THREW__
183-
; CHECK-NEXT: store i32 %value, i32* @__threwValue
184-
; CHECK-NEXT: br label %if.end
185-
; CHECK: if.end:
186-
; CHECK-NEXT: ret void
187-
; CHECK: }
188-
189-
; setTempRet0 function creation
190-
; CHECK-LABEL: define weak_odr void @setTempRet0(i32 %value) {
191-
; CHECK: entry:
192-
; CHECK-NEXT: store i32 %value, i32* @__tempRet0
193-
; CHECK-NEXT: ret void
194-
; CHECK: }

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ target triple = "wasm32-unknown-unknown"
66
%struct.__jmp_buf_tag = type { [6 x i32], i32, [32 x i32] }
77

88
@global_var = hidden global i32 0, align 4
9-
; CHECK-DAG: __THREW__ = weak_odr global i32 0
10-
; CHECK-DAG: __threwValue = weak_odr global i32 0
11-
; CHECK-DAG: __tempRet0 = weak_odr global i32 0
9+
; CHECK-DAG: __THREW__ = external global i32
10+
; CHECK-DAG: __threwValue = external global i32
11+
; CHECK-DAG: __tempRet0 = external global i32
1212

1313
; Test a simple setjmp - longjmp sequence
1414
define hidden void @setjmp_longjmp() {

0 commit comments

Comments
 (0)