OLD | NEW |
---|---|
1 //===-- JSBackend.cpp - Library for converting LLVM code to JS -----===// | 1 //===-- JSBackend.cpp - Library for converting LLVM code to JS -----===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements compiling of LLVM IR, which is assumed to have been | 10 // This file implements compiling of LLVM IR, which is assumed to have been |
(...skipping 14 matching lines...) Expand all Loading... | |
25 #include "llvm/Config/config.h" | 25 #include "llvm/Config/config.h" |
26 #include "llvm/IR/Constants.h" | 26 #include "llvm/IR/Constants.h" |
27 #include "llvm/IR/DerivedTypes.h" | 27 #include "llvm/IR/DerivedTypes.h" |
28 #include "llvm/IR/InlineAsm.h" | 28 #include "llvm/IR/InlineAsm.h" |
29 #include "llvm/IR/Instruction.h" | 29 #include "llvm/IR/Instruction.h" |
30 #include "llvm/IR/Instructions.h" | 30 #include "llvm/IR/Instructions.h" |
31 #include "llvm/IR/Intrinsics.h" | 31 #include "llvm/IR/Intrinsics.h" |
32 #include "llvm/IR/Module.h" | 32 #include "llvm/IR/Module.h" |
33 #include "llvm/IR/Operator.h" | 33 #include "llvm/IR/Operator.h" |
34 #include "llvm/Pass.h" | 34 #include "llvm/Pass.h" |
35 #include "llvm/PassManager.h" | 35 #include "llvm/IR/LegacyPassManager.h" |
36 #include "llvm/IR/CallSite.h" | 36 #include "llvm/IR/CallSite.h" |
37 #include "llvm/Support/CommandLine.h" | 37 #include "llvm/Support/CommandLine.h" |
38 #include "llvm/Support/ErrorHandling.h" | 38 #include "llvm/Support/ErrorHandling.h" |
39 #include "llvm/Support/FormattedStream.h" | |
40 #include "llvm/IR/GetElementPtrTypeIterator.h" | 39 #include "llvm/IR/GetElementPtrTypeIterator.h" |
41 #include "llvm/Support/MathExtras.h" | 40 #include "llvm/Support/MathExtras.h" |
42 #include "llvm/Support/TargetRegistry.h" | 41 #include "llvm/Support/TargetRegistry.h" |
43 #include "llvm/IR/DebugInfo.h" | 42 #include "llvm/IR/DebugInfo.h" |
44 #include "llvm/Transforms/NaCl.h" | 43 #include "llvm/Transforms/NaCl.h" |
45 #include <algorithm> | 44 #include <algorithm> |
46 #include <cstdio> | 45 #include <cstdio> |
47 #include <map> | 46 #include <map> |
48 #include <set> // TODO: unordered_set? | 47 #include <set> // TODO: unordered_set? |
49 using namespace llvm; | 48 using namespace llvm; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 typedef std::map<std::string, FunctionTable> FunctionTableMap; | 121 typedef std::map<std::string, FunctionTable> FunctionTableMap; |
123 typedef std::map<std::string, std::string> StringMap; | 122 typedef std::map<std::string, std::string> StringMap; |
124 typedef std::map<std::string, unsigned> NameIntMap; | 123 typedef std::map<std::string, unsigned> NameIntMap; |
125 typedef std::map<const BasicBlock*, unsigned> BlockIndexMap; | 124 typedef std::map<const BasicBlock*, unsigned> BlockIndexMap; |
126 typedef std::map<const Function*, BlockIndexMap> BlockAddressMap; | 125 typedef std::map<const Function*, BlockIndexMap> BlockAddressMap; |
127 typedef std::map<const BasicBlock*, Block*> LLVMToRelooperMap; | 126 typedef std::map<const BasicBlock*, Block*> LLVMToRelooperMap; |
128 | 127 |
129 /// JSWriter - This class is the main chunk of code that converts an LLVM | 128 /// JSWriter - This class is the main chunk of code that converts an LLVM |
130 /// module to JavaScript. | 129 /// module to JavaScript. |
131 class JSWriter : public ModulePass { | 130 class JSWriter : public ModulePass { |
132 formatted_raw_ostream &Out; | 131 raw_pwrite_stream &Out; |
133 const Module *TheModule; | 132 const Module *TheModule; |
134 unsigned UniqueNum; | 133 unsigned UniqueNum; |
135 unsigned NextFunctionIndex; // used with NoAliasingFunctionPointers | 134 unsigned NextFunctionIndex; // used with NoAliasingFunctionPointers |
136 ValueMap ValueNames; | 135 ValueMap ValueNames; |
137 VarMap UsedVars; | 136 VarMap UsedVars; |
138 AllocaManager Allocas; | 137 AllocaManager Allocas; |
139 HeapData GlobalData8; | 138 HeapData GlobalData8; |
140 HeapData GlobalData32; | 139 HeapData GlobalData32; |
141 HeapData GlobalData64; | 140 HeapData GlobalData64; |
142 GlobalAddressMap GlobalAddresses; | 141 GlobalAddressMap GlobalAddresses; |
143 NameSet Externals; // vars | 142 NameSet Externals; // vars |
144 NameSet Declares; // funcs | 143 NameSet Declares; // funcs |
145 StringMap Redirects; // library function redirects actually used, needed for wrapper funcs in tables | 144 StringMap Redirects; // library function redirects actually used, needed for wrapper funcs in tables |
146 std::string PostSets; | 145 std::string PostSets; |
147 NameIntMap NamedGlobals; // globals that we export as metadata to JS, so it can access them by name | 146 NameIntMap NamedGlobals; // globals that we export as metadata to JS, so it can access them by name |
148 std::map<std::string, unsigned> IndexedFunctions; // name -> index | 147 std::map<std::string, unsigned> IndexedFunctions; // name -> index |
149 FunctionTableMap FunctionTables; // sig => list of functions | 148 FunctionTableMap FunctionTables; // sig => list of functions |
150 std::vector<std::string> GlobalInitializers; | 149 std::vector<std::string> GlobalInitializers; |
151 std::vector<std::string> Exports; // additional exports | 150 std::vector<std::string> Exports; // additional exports |
152 BlockAddressMap BlockAddresses; | 151 BlockAddressMap BlockAddresses; |
153 | 152 |
154 std::string CantValidate; | 153 std::string CantValidate; |
155 bool UsesSIMD; | 154 bool UsesSIMD; |
156 int InvokeState; // cycles between 0, 1 after preInvoke, 2 after call, 0 aga in after postInvoke. hackish, no argument there. | 155 int InvokeState; // cycles between 0, 1 after preInvoke, 2 after call, 0 aga in after postInvoke. hackish, no argument there. |
157 CodeGenOpt::Level OptLevel; | 156 CodeGenOpt::Level OptLevel; |
158 const DataLayout *DL; | 157 const DataLayout *DL; |
jvoung (off chromium)
2015/05/26 20:39:45
Upstream whitespace change, or leave the space alo
Derek Schuff
2015/05/26 22:01:32
Done.
| |
159 bool StackBumped; | 158 bool StackBumped; |
160 | 159 |
161 #include "CallHandlers.h" | 160 #include "CallHandlers.h" |
162 | 161 |
163 public: | 162 public: |
164 static char ID; | 163 static char ID; |
165 JSWriter(formatted_raw_ostream &o, CodeGenOpt::Level OptLevel) | 164 JSWriter(raw_pwrite_stream &o, CodeGenOpt::Level OptLevel) |
166 : ModulePass(ID), Out(o), UniqueNum(0), NextFunctionIndex(0), CantValidate (""), UsesSIMD(false), InvokeState(0), | 165 : ModulePass(ID), Out(o), UniqueNum(0), NextFunctionIndex(0), CantValidate (""), UsesSIMD(false), InvokeState(0), |
167 OptLevel(OptLevel), StackBumped(false) {} | 166 OptLevel(OptLevel), StackBumped(false) {} |
168 | 167 |
169 virtual const char *getPassName() const { return "JavaScript backend"; } | 168 virtual const char *getPassName() const { return "JavaScript backend"; } |
170 | 169 |
171 virtual bool runOnModule(Module &M); | 170 virtual bool runOnModule(Module &M); |
172 | 171 |
173 virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 172 virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
174 AU.setPreservesAll(); | 173 AU.setPreservesAll(); |
175 AU.addRequired<DataLayoutPass>(); | |
176 ModulePass::getAnalysisUsage(AU); | 174 ModulePass::getAnalysisUsage(AU); |
177 } | 175 } |
178 | 176 |
179 void printProgram(const std::string& fname, const std::string& modName ); | 177 void printProgram(const std::string& fname, const std::string& modName ); |
180 void printModule(const std::string& fname, const std::string& modName ); | 178 void printModule(const std::string& fname, const std::string& modName ); |
181 void printFunction(const Function *F); | 179 void printFunction(const Function *F); |
182 | 180 |
183 LLVM_ATTRIBUTE_NORETURN void error(const std::string& msg); | 181 LLVM_ATTRIBUTE_NORETURN void error(const std::string& msg); |
184 | 182 |
185 formatted_raw_ostream& nl(formatted_raw_ostream &Out, int delta = 0); | 183 raw_pwrite_stream& nl(raw_pwrite_stream &Out, int delta = 0); |
186 | 184 |
187 private: | 185 private: |
188 void printCommaSeparated(const HeapData v); | 186 void printCommaSeparated(const HeapData v); |
189 | 187 |
190 // parsing of constants has two phases: calculate, and then emit | 188 // parsing of constants has two phases: calculate, and then emit |
191 void parseConstant(const std::string& name, const Constant* CV, bool calcula te); | 189 void parseConstant(const std::string& name, const Constant* CV, bool calcula te); |
192 | 190 |
193 #define MEM_ALIGN 8 | 191 #define MEM_ALIGN 8 |
194 #define MEM_ALIGN_BITS 64 | 192 #define MEM_ALIGN_BITS 64 |
195 #define STACK_ALIGN 16 | 193 #define STACK_ALIGN 16 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
475 // special analyses | 473 // special analyses |
476 | 474 |
477 bool canReloop(const Function *F); | 475 bool canReloop(const Function *F); |
478 | 476 |
479 // main entry point | 477 // main entry point |
480 | 478 |
481 void printModuleBody(); | 479 void printModuleBody(); |
482 }; | 480 }; |
483 } // end anonymous namespace. | 481 } // end anonymous namespace. |
484 | 482 |
485 formatted_raw_ostream &JSWriter::nl(formatted_raw_ostream &Out, int delta) { | 483 raw_pwrite_stream &JSWriter::nl(raw_pwrite_stream &Out, int delta) { |
486 Out << '\n'; | 484 Out << '\n'; |
487 return Out; | 485 return Out; |
488 } | 486 } |
489 | 487 |
490 static inline char halfCharToHex(unsigned char half) { | 488 static inline char halfCharToHex(unsigned char half) { |
491 assert(half <= 15); | 489 assert(half <= 15); |
492 if (half <= 9) { | 490 if (half <= 9) { |
493 return '0' + half; | 491 return '0' + half; |
494 } else { | 492 } else { |
495 return 'A' + half - 10; | 493 return 'A' + half - 10; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
556 } | 554 } |
557 | 555 |
558 static inline std::string ensureFloat(const std::string &S, Type *T) { | 556 static inline std::string ensureFloat(const std::string &S, Type *T) { |
559 if (PreciseF32 && T->isFloatTy()) { | 557 if (PreciseF32 && T->isFloatTy()) { |
560 return "Math_fround(" + S + ")"; | 558 return "Math_fround(" + S + ")"; |
561 } | 559 } |
562 return S; | 560 return S; |
563 } | 561 } |
564 | 562 |
565 static void emitDebugInfo(raw_ostream& Code, const Instruction *I) { | 563 static void emitDebugInfo(raw_ostream& Code, const Instruction *I) { |
566 if (MDNode *N = I->getMetadata("dbg")) { | 564 auto &Loc = I->getDebugLoc(); |
567 DILocation Loc(N); | 565 if (Loc) { |
568 unsigned Line = Loc.getLineNumber(); | 566 unsigned Line = Loc.getLine(); |
569 StringRef File = Loc.getFilename(); | 567 StringRef File = cast<MDLocation>(Loc.getScope())->getFilename(); |
570 Code << " //@line " << utostr(Line) << " \"" << (File.size() > 0 ? File.str( ) : "?") << "\""; | 568 Code << " //@line " << utostr(Line) << " \"" << (File.size() > 0 ? File.str( ) : "?") << "\""; |
571 } | 569 } |
572 } | 570 } |
573 | 571 |
574 void JSWriter::error(const std::string& msg) { | 572 void JSWriter::error(const std::string& msg) { |
575 report_fatal_error(msg); | 573 report_fatal_error(msg); |
576 } | 574 } |
577 | 575 |
578 std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) { | 576 std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) { |
579 // FIXME this is all quite inefficient, and also done once per incoming to eac h phi | 577 // FIXME this is all quite inefficient, and also done once per incoming to eac h phi |
(...skipping 2258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2838 Data = cast<ConstantInt>(CE->getOperand(1))->getZExtValue(); | 2836 Data = cast<ConstantInt>(CE->getOperand(1))->getZExtValue(); |
2839 CE = cast<ConstantExpr>(CE->getOperand(0)); | 2837 CE = cast<ConstantExpr>(CE->getOperand(0)); |
2840 } | 2838 } |
2841 const Value *V = CE; | 2839 const Value *V = CE; |
2842 if (CE->getOpcode() == Instruction::PtrToInt) { | 2840 if (CE->getOpcode() == Instruction::PtrToInt) { |
2843 V = CE->getOperand(0); | 2841 V = CE->getOperand(0); |
2844 } | 2842 } |
2845 | 2843 |
2846 // Deconstruct getelementptrs. | 2844 // Deconstruct getelementptrs. |
2847 int64_t BaseOffset; | 2845 int64_t BaseOffset; |
2848 V = GetPointerBaseWithConstantOffset(V, BaseOffset, DL); | 2846 V = GetPointerBaseWithConstantOffset(V, BaseOffset, *DL); |
2849 Data += (uint64_t)BaseOffset; | 2847 Data += (uint64_t)BaseOffset; |
2850 | 2848 |
2851 Data += getConstAsOffset(V, getGlobalAddress(name)); | 2849 Data += getConstAsOffset(V, getGlobalAddress(name)); |
2852 union { unsigned i; unsigned char b[sizeof(unsigned)]; } integer; | 2850 union { unsigned i; unsigned char b[sizeof(unsigned)]; } integer; |
2853 integer.i = Data; | 2851 integer.i = Data; |
2854 unsigned Offset = getRelativeGlobalAddress(name); | 2852 unsigned Offset = getRelativeGlobalAddress(name); |
2855 assert(Offset+4 <= GlobalData64.size()); | 2853 assert(Offset+4 <= GlobalData64.size()); |
2856 for (unsigned i = 0; i < 4; ++i) { | 2854 for (unsigned i = 0; i < 4; ++i) { |
2857 GlobalData64[Offset++] = integer.b[i]; | 2855 GlobalData64[Offset++] = integer.b[i]; |
2858 } | 2856 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2920 printModule(fname,mName); | 2918 printModule(fname,mName); |
2921 } | 2919 } |
2922 | 2920 |
2923 void JSWriter::printModule(const std::string& fname, | 2921 void JSWriter::printModule(const std::string& fname, |
2924 const std::string& mName) { | 2922 const std::string& mName) { |
2925 printModuleBody(); | 2923 printModuleBody(); |
2926 } | 2924 } |
2927 | 2925 |
2928 bool JSWriter::runOnModule(Module &M) { | 2926 bool JSWriter::runOnModule(Module &M) { |
2929 TheModule = &M; | 2927 TheModule = &M; |
2930 DL = &getAnalysis<DataLayoutPass>().getDataLayout(); | 2928 DL = &M.getDataLayout(); |
2931 | 2929 |
2932 setupCallHandlers(); | 2930 setupCallHandlers(); |
2933 | 2931 |
2934 printProgram("", ""); | 2932 printProgram("", ""); |
2935 | 2933 |
2936 return false; | 2934 return false; |
2937 } | 2935 } |
2938 | 2936 |
2939 char JSWriter::ID = 0; | 2937 char JSWriter::ID = 0; |
2940 | 2938 |
(...skipping 13 matching lines...) Expand all Loading... | |
2954 | 2952 |
2955 Pass *createCheckTriplePass() { | 2953 Pass *createCheckTriplePass() { |
2956 return new CheckTriple(); | 2954 return new CheckTriple(); |
2957 } | 2955 } |
2958 | 2956 |
2959 //===----------------------------------------------------------------------===// | 2957 //===----------------------------------------------------------------------===// |
2960 // External Interface declaration | 2958 // External Interface declaration |
2961 //===----------------------------------------------------------------------===// | 2959 //===----------------------------------------------------------------------===// |
2962 | 2960 |
2963 bool JSTargetMachine::addPassesToEmitFile(PassManagerBase &PM, | 2961 bool JSTargetMachine::addPassesToEmitFile(PassManagerBase &PM, |
2964 formatted_raw_ostream &o, | 2962 raw_pwrite_stream &o, |
2965 CodeGenFileType FileType, | 2963 CodeGenFileType FileType, |
2966 bool DisableVerify, | 2964 bool DisableVerify, |
2967 AnalysisID StartAfter, | 2965 AnalysisID StartAfter, |
2968 AnalysisID StopAfter) { | 2966 AnalysisID StopAfter) { |
2969 assert(FileType == TargetMachine::CGFT_AssemblyFile); | 2967 assert(FileType == TargetMachine::CGFT_AssemblyFile); |
2970 | 2968 |
2971 PM.add(createCheckTriplePass()); | 2969 PM.add(createCheckTriplePass()); |
2972 PM.add(createExpandInsertExtractElementPass()); | 2970 PM.add(createExpandInsertExtractElementPass()); |
2973 PM.add(createExpandI64Pass()); | 2971 PM.add(createExpandI64Pass()); |
2974 | 2972 |
2975 CodeGenOpt::Level OptLevel = getOptLevel(); | 2973 CodeGenOpt::Level OptLevel = getOptLevel(); |
2976 | 2974 |
2977 // When optimizing, there shouldn't be any opportunities for SimplifyAllocas | 2975 // When optimizing, there shouldn't be any opportunities for SimplifyAllocas |
2978 // because the regular optimizer should have taken them all (GVN, and possibly | 2976 // because the regular optimizer should have taken them all (GVN, and possibly |
2979 // also SROA). | 2977 // also SROA). |
2980 if (OptLevel == CodeGenOpt::None) | 2978 if (OptLevel == CodeGenOpt::None) |
2981 PM.add(createEmscriptenSimplifyAllocasPass()); | 2979 PM.add(createEmscriptenSimplifyAllocasPass()); |
2982 | 2980 |
2983 PM.add(new JSWriter(o, OptLevel)); | 2981 PM.add(new JSWriter(o, OptLevel)); |
2984 | 2982 |
2985 return false; | 2983 return false; |
2986 } | 2984 } |
OLD | NEW |