Chromium Code Reviews| 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 |