50
50
// /
51
51
// / In detail, this pass does following things:
52
52
// /
53
- // / 1) Create three global variables: __THREW__, __threwValue, and __tempRet0.
53
+ // / 1) Assumes the existence of global variables: __THREW__, __threwValue, and
54
+ // / __tempRet0.
54
55
// / __tempRet0 will be set within __cxa_find_matching_catch() function in
55
56
// / JS library, and __THREW__ and __threwValue will be set in invoke wrappers
56
57
// / in JS glue code. For what invoke wrappers are, refer to 3). These
65
66
// /
66
67
// / * Exception handling
67
68
// /
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
71
73
// / as interfaces to JS glue code. These functions are equivalent to the
72
74
// / following JS functions, which actually exist in asm.js version of JS
73
75
// / library.
@@ -272,9 +274,6 @@ class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass {
272
274
bool areAllExceptionsAllowed () const { return EHWhitelistSet.empty (); }
273
275
bool canLongjmp (Module &M, const Value *Callee) const ;
274
276
275
- void createSetThrewFunction (Module &M);
276
- void createSetTempRet0Function (Module &M);
277
-
278
277
void rebuildSSA (Function &F);
279
278
280
279
public:
@@ -333,13 +332,15 @@ static bool canThrow(const Value *V) {
333
332
return true ;
334
333
}
335
334
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) {
338
339
if (M.getNamedGlobal (Name))
339
340
report_fatal_error (Twine (" variable name is reserved: " ) + Name);
340
341
341
342
return new GlobalVariable (M, IRB.getInt32Ty (), false ,
342
- GlobalValue::WeakODRLinkage, IRB. getInt32 ( 0 ) , Name);
343
+ GlobalValue::ExternalLinkage, nullptr , Name);
343
344
}
344
345
345
346
// Simple function name mangler.
@@ -590,67 +591,6 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp(
590
591
LongjmpResult = IRB.CreateLoad (TempRet0GV, " longjmp_result" );
591
592
}
592
593
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
-
654
594
void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA (Function &F) {
655
595
DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(F).getDomTree ();
656
596
DT.recalculate (F); // CFG has been changed
@@ -688,11 +628,12 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
688
628
bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty ();
689
629
bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed);
690
630
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" );
696
637
697
638
bool Changed = false ;
698
639
@@ -764,9 +705,6 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
764
705
765
706
if (!Changed) {
766
707
// Delete unused global variables and functions
767
- ThrewGV->eraseFromParent ();
768
- ThrewValueGV->eraseFromParent ();
769
- TempRet0GV->eraseFromParent ();
770
708
if (ResumeF)
771
709
ResumeF->eraseFromParent ();
772
710
if (EHTypeIDF)
@@ -780,12 +718,6 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
780
718
return false ;
781
719
}
782
720
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
-
789
721
return true ;
790
722
}
791
723
0 commit comments