@@ -116,68 +116,6 @@ void EmscriptenGlueGenerator::generatePostInstantiateFunction() {
116
116
wasm.addExport (ex);
117
117
}
118
118
119
- inline void exportFunction (Module& wasm, Name name, bool must_export) {
120
- if (!wasm.getFunctionOrNull (name)) {
121
- assert (!must_export);
122
- return ;
123
- }
124
- if (wasm.getExportOrNull (name)) {
125
- return ; // Already exported
126
- }
127
- auto exp = new Export;
128
- exp ->name = exp ->value = name;
129
- exp ->kind = ExternalKind::Function;
130
- wasm.addExport (exp );
131
- }
132
-
133
- static bool hasI64 (Signature sig) {
134
- // We only generate dynCall functions for signatures that contain
135
- // i64. This is because any other function can be called directly
136
- // from JavaScript using the wasm table.
137
- for (auto t : sig.results ) {
138
- if (t.getID () == Type::i64) {
139
- return true ;
140
- }
141
- }
142
- for (auto t : sig.params ) {
143
- if (t.getID () == Type::i64) {
144
- return true ;
145
- }
146
- }
147
- return false ;
148
- }
149
-
150
- void EmscriptenGlueGenerator::generateDynCallThunk (Signature sig) {
151
- if (noDynCalls || (onlyI64DynCalls && !hasI64 (sig))) {
152
- return ;
153
- }
154
- if (!sigs.insert (sig).second ) {
155
- return ; // sig is already in the set
156
- }
157
- Name name = std::string (" dynCall_" ) + getSig (sig.results , sig.params );
158
- if (wasm.getFunctionOrNull (name) || wasm.getExportOrNull (name)) {
159
- return ; // module already contains this dyncall
160
- }
161
- std::vector<NameType> params;
162
- params.emplace_back (" fptr" , Type::i32); // function pointer param
163
- int p = 0 ;
164
- for (const auto & param : sig.params ) {
165
- params.emplace_back (std::to_string (p++), param);
166
- }
167
- Function* f = builder.makeFunction (name, std::move (params), sig.results , {});
168
- Expression* fptr = builder.makeLocalGet (0 , Type::i32);
169
- std::vector<Expression*> args;
170
- Index i = 0 ;
171
- for (const auto & param : sig.params ) {
172
- args.push_back (builder.makeLocalGet (++i, param));
173
- }
174
- Expression* call = builder.makeCallIndirect (fptr, args, sig);
175
- f->body = call;
176
-
177
- wasm.addFunction (f);
178
- exportFunction (wasm, f->name , true );
179
- }
180
-
181
119
// lld can sometimes produce a build with an imported mutable __stack_pointer
182
120
// (i.e. when linking with -fpie). This method internalizes the
183
121
// __stack_pointer and initializes it from an immutable global instead.
@@ -549,138 +487,6 @@ EmJsWalker fixEmJsFuncsAndReturnWalker(Module& wasm) {
549
487
return walker;
550
488
}
551
489
552
- // Fixes function name hacks caused by LLVM exception & setjmp/longjmp
553
- // handling pass for wasm.
554
- // This does two things:
555
- // 1. Change emscripten_longjmp_jmpbuf to emscripten_longjmp.
556
- // In setjmp/longjmp handling pass in wasm backend, what we want to do is
557
- // to change all function calls to longjmp to calls to emscripten_longjmp.
558
- // Because we replace all calls to longjmp to emscripten_longjmp, the
559
- // signature of that function should be the same as longjmp:
560
- // emscripten_longjmp(jmp_buf, int)
561
- // But after calling a function that might longjmp, while we test whether
562
- // a longjmp occurred, we have to load an int address value and call
563
- // emscripten_longjmp again with that address as the first argument. (Refer
564
- // to lib/Target/WebAssembly/WebAssemblyEmscriptenEHSjLj.cpp in LLVM for
565
- // details.)
566
- // In this case we need the signature of emscripten_longjmp to be (int,
567
- // int). So we need two different kinds of emscripten_longjmp signatures in
568
- // LLVM IR. Both signatures will be lowered to (int, int) eventually, but
569
- // in LLVM IR, types are not lowered yet.
570
- // So we declare two functions in LLVM:
571
- // emscripten_longjmp_jmpbuf(jmp_buf, int)
572
- // emscripten_longjmp(int, int)
573
- // And we change the name of emscripten_longjmp_jmpbuf to
574
- // emscripten_longjmp here.
575
- // 2. Converts invoke wrapper names.
576
- // Refer to the comments in fixEmExceptionInvoke below.
577
- struct FixInvokeFunctionNamesWalker
578
- : public PostWalker<FixInvokeFunctionNamesWalker> {
579
- Module& wasm;
580
- std::vector<Name> toRemove;
581
- std::map<Name, Name> importRenames;
582
- std::map<Name, Name> functionRenames;
583
- std::set<Signature> invokeSigs;
584
- ImportInfo imports;
585
-
586
- FixInvokeFunctionNamesWalker (Module& _wasm) : wasm(_wasm), imports(wasm) {}
587
-
588
- // Converts invoke wrapper names generated by LLVM backend to real invoke
589
- // wrapper names that are expected by JavaScript glue code.
590
- // This is required to support wasm exception handling (asm.js style).
591
- //
592
- // LLVM backend lowers
593
- // invoke @func(arg1, arg2) to label %invoke.cont unwind label %lpad
594
- // into
595
- // ... (some code)
596
- // call @invoke_SIG(func, arg1, arg2)
597
- // ... (some code)
598
- // SIG is a mangled string generated based on the LLVM IR-level function
599
- // signature. In LLVM IR, types are not lowered yet, so this mangling scheme
600
- // simply takes LLVM's string representtion of parameter types and concatenate
601
- // them with '_'. For example, the name of an invoke wrapper for function
602
- // void foo(struct mystruct*, int) will be
603
- // "__invoke_void_%struct.mystruct*_int".
604
- // This function converts the names of invoke wrappers based on their lowered
605
- // argument types and a return type. In the example above, the resulting new
606
- // wrapper name becomes "invoke_vii".
607
- Name fixEmExceptionInvoke (const Name& name, Signature sig) {
608
- std::string nameStr = name.c_str ();
609
- if (nameStr.front () == ' "' && nameStr.back () == ' "' ) {
610
- nameStr = nameStr.substr (1 , nameStr.size () - 2 );
611
- }
612
- if (nameStr.find (" __invoke_" ) != 0 ) {
613
- return name;
614
- }
615
-
616
- std::vector<Type> newParams (sig.params .begin () + 1 , sig.params .end ());
617
- Signature sigWoOrigFunc = Signature (Type (newParams), sig.results );
618
- invokeSigs.insert (sigWoOrigFunc);
619
- return Name (" invoke_" +
620
- getSig (sigWoOrigFunc.results , sigWoOrigFunc.params ));
621
- }
622
-
623
- void visitFunction (Function* curr) {
624
- if (!curr->imported ()) {
625
- return ;
626
- }
627
-
628
- Name newname = fixEmExceptionInvoke (curr->base , curr->sig );
629
- if (newname == curr->base ) {
630
- return ;
631
- }
632
-
633
- BYN_TRACE (" renaming import: " << curr->module << " ." << curr->base << " ("
634
- << curr->name << " ) -> " << newname << " \n " );
635
-
636
- if (auto * f = imports.getImportedFunction (curr->module , newname)) {
637
- BYN_TRACE (" remove redundant import: " << curr->base << " \n " );
638
- toRemove.push_back (curr->name );
639
- // Make sure the existing import has the correct internal name.
640
- if (f->name != newname) {
641
- functionRenames[f->name ] = newname;
642
- }
643
- } else {
644
- BYN_TRACE (" rename import: " << curr->base << " \n " );
645
- curr->base = newname;
646
- }
647
-
648
- functionRenames[curr->name ] = newname;
649
-
650
- // Ensure that an imported functions of this name exists.
651
- importRenames[curr->base ] = newname;
652
- }
653
-
654
- void visitModule (Module* curr) {
655
- for (auto name : toRemove) {
656
- wasm.removeFunction (name);
657
- }
658
-
659
- // Rename all uses of the old function to the new import name
660
- ModuleUtils::renameFunctions (wasm, functionRenames);
661
-
662
- // For imports that for renamed, update any associated GOT.func imports.
663
- for (auto & pair : importRenames) {
664
- BYN_TRACE (" looking for: GOT.func." << pair.first << " \n " );
665
- if (auto g = imports.getImportedGlobal (" GOT.func" , pair.first )) {
666
- BYN_TRACE (" renaming corresponding GOT entry: " << g->base << " -> "
667
- << pair.second << " \n " );
668
- g->base = pair.second ;
669
- }
670
- }
671
- }
672
- };
673
-
674
- void EmscriptenGlueGenerator::fixInvokeFunctionNames () {
675
- BYN_TRACE (" fixInvokeFunctionNames\n " );
676
- FixInvokeFunctionNamesWalker walker (wasm);
677
- walker.walkModule (&wasm);
678
- BYN_TRACE (" generating dyncall thunks\n " );
679
- for (auto sig : walker.invokeSigs ) {
680
- generateDynCallThunk (sig);
681
- }
682
- }
683
-
684
490
void printSignatures (std::ostream& o, const std::set<Signature>& c) {
685
491
o << " [" ;
686
492
bool first = true ;
0 commit comments