diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-02-13 10:57:20 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-02-13 10:57:20 -0800 |
commit | 04faad37ba15e237c87e58e9914a998a3d7a2ed1 (patch) | |
tree | a7c10dbce5f13c4badecacd1f6de052606b354ae /lib/Target/JSBackend/JSBackend.cpp | |
parent | 08cdac187ad3a109d5e68c771ca2b2d2e23d9e3f (diff) | |
parent | 718e02f4cea34a6f34d7a6f1f82411960bff1ba4 (diff) |
Merge pull request #11 from sunfishcode/incoming
Several patches
Diffstat (limited to 'lib/Target/JSBackend/JSBackend.cpp')
-rw-r--r-- | lib/Target/JSBackend/JSBackend.cpp | 143 |
1 files changed, 77 insertions, 66 deletions
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index bef17bd545..174e6b1141 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -48,18 +48,10 @@ using namespace llvm; #define snprintf _snprintf #endif -#define dump(x) fprintf(stderr, x "\n") -#define dumpv(x, ...) fprintf(stderr, x "\n", __VA_ARGS__) -#define dumpfail(x) { fputs(x "\n", stderr); fprintf(stderr, "%s : %d\n", __FILE__, __LINE__); report_fatal_error("fail"); } -#define dumpfailv(x, ...) { fprintf(stderr, x "\n", __VA_ARGS__); fprintf(stderr, "%s : %d\n", __FILE__, __LINE__); report_fatal_error("fail"); } -#define dumpIR(value) { \ - std::string temp; \ - raw_string_ostream stream(temp); \ - stream << *(value); \ - fprintf(stderr, "%s\n", temp.c_str()); \ -} +#ifdef NDEBUG #undef assert -#define assert(x) { if (!(x)) dumpfail(#x); } +#define assert(x) { if (!(x)) report_fatal_error(#x); } +#endif static cl::opt<bool> PreciseF32("emscripten-precise-f32", @@ -84,8 +76,8 @@ namespace { #define ASM_FFI_OUT 8 // params to FFIs are limited to things that work in ffis typedef unsigned AsmCast; - const char *SIMDLane = "XYZW"; - const char *simdLane = "xyzw"; + const char *const SIMDLane = "XYZW"; + const char *const simdLane = "xyzw"; typedef std::map<const Value*,std::string> ValueMap; typedef std::set<std::string> NameSet; @@ -125,6 +117,7 @@ namespace { bool UsesSIMD; int InvokeState; // cycles between 0, 1 after preInvoke, 2 after call, 0 again after postInvoke. hackish, no argument there. + DataLayout *DL; #include "CallHandlers.h" @@ -134,7 +127,13 @@ namespace { virtual const char *getPassName() const { return "JavaScript backend"; } - bool runOnModule(Module &M); + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<DataLayout>(); + ModulePass::getAnalysisUsage(AU); + } void printProgram(const std::string& fname, const std::string& modName ); void printModule(const std::string& fname, const std::string& modName ); @@ -167,7 +166,7 @@ namespace { case 8: GlobalData = &GlobalData8; break; case 32: GlobalData = &GlobalData32; break; case 64: GlobalData = &GlobalData64; break; - default: assert(false); + default: llvm_unreachable("Unsupported data element size"); } while (GlobalData->size() % (Bits/8) != 0) GlobalData->push_back(0); GlobalAddresses[Name] = Address(GlobalData->size(), Bits); @@ -178,8 +177,11 @@ namespace { // return the absolute offset of a global unsigned getGlobalAddress(const std::string &s) { - if (GlobalAddresses.find(s) == GlobalAddresses.end()) dumpfailv("cannot find global address %s", s.c_str()); - Address a = GlobalAddresses[s]; + GlobalAddressMap::const_iterator I = GlobalAddresses.find(s); + if (I == GlobalAddresses.end()) { + report_fatal_error("cannot find global address " + Twine(s)); + } + Address a = I->second; assert(a.second == 64); // FIXME when we use optimal alignments unsigned Ret; switch (a.second) { @@ -195,7 +197,9 @@ namespace { Ret = a.first + GLOBAL_BASE + GlobalData64.size() + GlobalData32.size(); break; default: - dumpfailv("bad global address %s %d %d\n", s.c_str(), a.first, a.second); + report_fatal_error("bad global address " + Twine(s) + ": " + "count=" + Twine(a.first) + " " + "elementsize=" + Twine(a.second)); } if (s == "_ZTVN10__cxxabiv119__pointer_type_infoE" || s == "_ZTVN10__cxxabiv117__class_type_infoE" || @@ -220,8 +224,11 @@ namespace { } // returns the internal offset inside the proper block: GlobalData8, 32, 64 unsigned getRelativeGlobalAddress(const std::string &s) { - if (GlobalAddresses.find(s) == GlobalAddresses.end()) dumpfailv("cannot find global address %s", s.c_str()); - Address a = GlobalAddresses[s]; + GlobalAddressMap::const_iterator I = GlobalAddresses.find(s); + if (I == GlobalAddresses.end()) { + report_fatal_error("cannot find global address " + Twine(s)); + } + Address a = I->second; return a.first; } char getFunctionSignatureLetter(Type *T) { @@ -265,7 +272,7 @@ namespace { IndexedFunctions[Name] = Index; // invoke the callHandler for this, if there is one. the function may only be indexed but never called directly, and we may need to do things in the handler - CallHandlerMap::iterator CH = CallHandlers->find(Name); + CallHandlerMap::const_iterator CH = CallHandlers->find(Name); if (CH != CallHandlers->end()) { (this->*(CH->second))(NULL, Name, -1); } @@ -295,6 +302,7 @@ namespace { } } std::string getPtrAsStr(const Value* Ptr) { + Ptr = Ptr->stripPointerCasts(); if (isa<const ConstantPointerNull>(Ptr)) return "0"; if (const Function *F = dyn_cast<Function>(Ptr)) { return utostr(getFunctionIndex(F)); @@ -405,7 +413,7 @@ std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) { // Find the phis, and generate assignments and dependencies typedef std::map<std::string, std::string> StringMap; StringMap assigns; // variable -> assign statement - std::map<std::string, Value*> values; // variable -> Value + std::map<std::string, const Value*> values; // variable -> Value StringMap deps; // variable -> dependency StringMap undeps; // reverse: dependency -> variable for (BasicBlock::const_iterator I = To->begin(), E = To->end(); @@ -417,7 +425,7 @@ std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) { // we found it const std::string &name = getJSName(P); assigns[name] = getAssign(name, P->getType()); - Value *V = P->getIncomingValue(index); + const Value *V = P->getIncomingValue(index); values[name] = V; std::string vname = getValueAsStr(V); if (const Instruction *VI = dyn_cast<const Instruction>(V)) { @@ -434,11 +442,11 @@ std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) { for (StringMap::iterator I = assigns.begin(); I != assigns.end();) { StringMap::iterator last = I; std::string curr = last->first; - Value *V = values[curr]; + const Value *V = values[curr]; std::string CV = getValueAsStr(V); I++; // advance now, as we may erase // if we have no dependencies, or we found none to emit and are at the end (so there is a cycle), emit - StringMap::iterator dep = deps.find(curr); + StringMap::const_iterator dep = deps.find(curr); if (dep == deps.end() || (!emitted && I == assigns.end())) { if (dep != deps.end()) { // break a cycle @@ -459,7 +467,7 @@ std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) { } const std::string &JSWriter::getJSName(const Value* val) { - ValueMap::iterator I = ValueNames.find(val); + ValueMap::const_iterator I = ValueNames.find(val); if (I != ValueNames.end() && I->first == val) return I->second; @@ -506,7 +514,7 @@ std::string JSWriter::getCast(const StringRef &s, const Type *t, AsmCast sign) { case 8: if (!(sign & ASM_NONSPECIFIC)) return sign == ASM_UNSIGNED ? (s + "&255").str() : (s + "<<24>>24").str(); case 16: if (!(sign & ASM_NONSPECIFIC)) return sign == ASM_UNSIGNED ? (s + "&65535").str() : (s + "<<16>>16").str(); case 32: return (sign == ASM_SIGNED || (sign & ASM_NONSPECIFIC) ? s + "|0" : s + ">>>0").str(); - default: assert(0); + default: llvm_unreachable("Unsupported integer cast bitwidth"); } } case Type::PointerTyID: return (s + "|0").str(); @@ -749,7 +757,7 @@ std::string JSWriter::getPtrLoad(const Value* Ptr) { std::string JSWriter::getHeapAccess(const std::string& Name, unsigned Bytes, bool Integer) { switch (Bytes) { - default: assert(false && "Unsupported type"); + default: llvm_unreachable("Unsupported type"); case 8: return "HEAPF64[" + Name + ">>3]"; case 4: { if (Integer) { @@ -770,7 +778,7 @@ std::string JSWriter::getPtrUse(const Value* Ptr) { std::string text = ""; unsigned Addr = getGlobalAddress(GV->getName().str()); switch (Bytes) { - default: assert(false && "Unsupported type"); + default: llvm_unreachable("Unsupported type"); case 8: return "HEAPF64[" + utostr(Addr >> 3) + "]"; case 4: { if (t->isIntegerTy()) { @@ -893,8 +901,8 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) { CV = CE->getOperand(0); // ignore bitcast return getPtrAsStr(CV); } else { - dumpIR(CV); - assert(false); + CV->dump(); + llvm_unreachable("Unsupported constant kind"); } } } @@ -940,7 +948,7 @@ bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instructi Code << getAssign(iName, I->getType()); switch (I->getOpcode()) { - default: dumpIR(I); error("invalid vector instr"); break; + default: I->dump(); error("invalid vector instr"); break; case Instruction::FAdd: Code << "SIMD.float32x4.add(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break; case Instruction::FMul: Code << "SIMD.float32x4.mul(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break; case Instruction::FDiv: Code << "SIMD.float32x4.div(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break; @@ -1058,13 +1066,13 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod if (!generateSIMDInstruction(iName, I, Code)) switch (I->getOpcode()) { default: { - dumpIR(I); + I->dump(); error("Invalid instruction"); break; } case Instruction::Ret: { const ReturnInst* ret = cast<ReturnInst>(I); - Value *RV = ret->getReturnValue(); + const Value *RV = ret->getReturnValue(); Code << "STACKTOP = sp;"; Code << "return"; if (RV == NULL) { @@ -1230,7 +1238,7 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod case ICmpInst::ICMP_SLT: Code << "<"; break; case ICmpInst::ICMP_UGT: Code << ">"; break; case ICmpInst::ICMP_SGT: Code << ">"; break; - default: assert(0); + default: llvm_unreachable("Invalid ICmp predicate"); } Code << "(" << getValueAsCastStr(I->getOperand(1), sign) << @@ -1302,6 +1310,10 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod } break; } + case Instruction::GetElementPtr: { + report_fatal_error("Unlowered getelementptr"); + break; + } case Instruction::PHI: { // handled separately - we push them back into the relooper branchings break; @@ -1480,7 +1492,7 @@ void JSWriter::printFunctionBody(const Function *F) { const TerminatorInst *TI = BI->getTerminator(); switch (TI->getOpcode()) { default: { - dumpfailv("invalid branch instr %s\n", TI->getOpcodeName()); + report_fatal_error("invalid branch instr " + Twine(TI->getOpcodeName())); break; } case Instruction::Br: { @@ -1525,7 +1537,7 @@ void JSWriter::printFunctionBody(const Function *F) { } BlocksToConditions[BB] = Condition + (!UseSwitch && BlocksToConditions[BB].size() > 0 ? " | " : "") + BlocksToConditions[BB]; } - for (BlockCondMap::iterator I = BlocksToConditions.begin(), E = BlocksToConditions.end(); I != E; ++I) { + for (BlockCondMap::const_iterator I = BlocksToConditions.begin(), E = BlocksToConditions.end(); I != E; ++I) { const BasicBlock *BB = I->first; std::string P = getPhiCode(&*BI, BB); LLVMToRelooper[&*BI]->AddBranchTo(LLVMToRelooper[&*BB], I->second.c_str(), P.size() > 0 ? P.c_str() : NULL); @@ -1546,7 +1558,7 @@ void JSWriter::printFunctionBody(const Function *F) { UsedVars["label"] = Type::getInt32Ty(F->getContext())->getTypeID(); if (!UsedVars.empty()) { unsigned Count = 0; - for (VarMap::iterator VI = UsedVars.begin(); VI != UsedVars.end(); ++VI) { + for (VarMap::const_iterator VI = UsedVars.begin(); VI != UsedVars.end(); ++VI) { if (Count == 20) { Out << ";\n"; Count = 0; @@ -1559,7 +1571,7 @@ void JSWriter::printFunctionBody(const Function *F) { Out << VI->first << " = "; switch (VI->second) { default: - assert(false); + llvm_unreachable("unsupported variable initializer type"); case Type::PointerTyID: case Type::IntegerTyID: Out << "0"; @@ -1743,7 +1755,7 @@ void JSWriter::printModuleBody() { Out << "\"" << I->getName() << "\""; } } - for (NameSet::iterator I = Declares.begin(), E = Declares.end(); + for (NameSet::const_iterator I = Declares.begin(), E = Declares.end(); I != E; ++I) { if (first) { first = false; @@ -1756,7 +1768,7 @@ void JSWriter::printModuleBody() { Out << "\"redirects\": {"; first = true; - for (StringMap::iterator I = Redirects.begin(), E = Redirects.end(); + for (StringMap::const_iterator I = Redirects.begin(), E = Redirects.end(); I != E; ++I) { if (first) { first = false; @@ -1769,7 +1781,7 @@ void JSWriter::printModuleBody() { Out << "\"externs\": ["; first = true; - for (NameSet::iterator I = Externals.begin(), E = Externals.end(); + for (NameSet::const_iterator I = Externals.begin(), E = Externals.end(); I != E; ++I) { if (first) { first = false; @@ -1844,7 +1856,7 @@ void JSWriter::printModuleBody() { Out << "\"namedGlobals\": {"; first = true; - for (NameIntMap::iterator I = NamedGlobals.begin(), E = NamedGlobals.end(); I != E; ++I) { + for (NameIntMap::const_iterator I = NamedGlobals.begin(), E = NamedGlobals.end(); I != E; ++I) { if (first) { first = false; } else { @@ -1860,7 +1872,7 @@ void JSWriter::printModuleBody() { void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool calculate) { if (isa<GlobalValue>(CV)) return; - //dumpv("parsing constant %s\n", name.c_str()); + //errs() << "parsing constant " << name << "\n"; // TODO: we repeat some work in both calculate and emit phases here // FIXME: use the proper optimal alignments if (const ConstantDataSequential *CDS = @@ -1894,7 +1906,7 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c } } } else { - assert(false); + assert(false && "Unsupported floating-point type"); } } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { if (calculate) { @@ -1909,11 +1921,10 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c } } } else if (isa<ConstantPointerNull>(CV)) { - assert(false); + assert(false && "Unlowered ConstantPointerNull"); } else if (isa<ConstantAggregateZero>(CV)) { if (calculate) { - DataLayout DL(TheModule); - unsigned Bytes = DL.getTypeStoreSize(CV->getType()); + unsigned Bytes = DL->getTypeStoreSize(CV->getType()); // FIXME: assume full 64-bit alignment for now Bytes = memAlign(Bytes); HeapData *GlobalData = allocateAddress(name); @@ -1951,8 +1962,7 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c } } else if (calculate) { HeapData *GlobalData = allocateAddress(name); - DataLayout DL(TheModule); - unsigned Bytes = DL.getTypeStoreSize(CV->getType()); + unsigned Bytes = DL->getTypeStoreSize(CV->getType()); for (unsigned i = 0; i < Bytes; ++i) { GlobalData->push_back(0); } @@ -1968,22 +1978,21 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c for (unsigned i = 0; i < Num; i++) { const Constant* C = CS->getOperand(i); if (isa<ConstantAggregateZero>(C)) { - DataLayout DL(TheModule); - unsigned Bytes = DL.getTypeStoreSize(C->getType()); + unsigned Bytes = DL->getTypeStoreSize(C->getType()); Offset += Bytes; // zeros, so just skip } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { - Value *V = CE->getOperand(0); + const Value *V = CE->getOperand(0); unsigned Data = 0; if (CE->getOpcode() == Instruction::PtrToInt) { Data = getConstAsOffset(V, Absolute + Offset - OffsetStart); } else if (CE->getOpcode() == Instruction::Add) { - V = dyn_cast<ConstantExpr>(V)->getOperand(0); + V = cast<ConstantExpr>(V)->getOperand(0); Data = getConstAsOffset(V, Absolute + Offset - OffsetStart); - ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(1)); + ConstantInt *CI = cast<ConstantInt>(CE->getOperand(1)); Data += *CI->getValue().getRawData(); } else { - dumpIR(CE); - assert(0); + CE->dump(); + llvm_unreachable("Unexpected constant expr kind"); } union { unsigned i; unsigned char b[sizeof(unsigned)]; } integer; integer.i = Data; @@ -1999,20 +2008,20 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c GlobalData64[Offset++] = Str.data()[i]; } } else { - dumpIR(C); - assert(0); + C->dump(); + llvm_unreachable("Unexpected constant kind"); } } } } else if (isa<ConstantVector>(CV)) { - assert(false); + assert(false && "Unlowered ConstantVector"); } else if (isa<BlockAddress>(CV)) { - assert(false); + assert(false && "Unlowered BlockAddress"); } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { if (name == "__init_array_start") { // this is the global static initializer if (calculate) { - Value *V = CE->getOperand(0); + const Value *V = CE->getOperand(0); GlobalInitializers.push_back(getJSName(V)); // is the func } @@ -2029,10 +2038,10 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c unsigned Data = 0; if (CE->getOpcode() == Instruction::Add) { Data = cast<ConstantInt>(CE->getOperand(1))->getZExtValue(); - CE = dyn_cast<ConstantExpr>(CE->getOperand(0)); + CE = cast<ConstantExpr>(CE->getOperand(0)); } assert(CE->isCast()); - Value *V = CE->getOperand(0); + const Value *V = CE->getOperand(0); Data += getConstAsOffset(V, getGlobalAddress(name)); union { unsigned i; unsigned char b[sizeof(unsigned)]; } integer; integer.i = Data; @@ -2044,9 +2053,10 @@ void JSWriter::parseConstant(const std::string& name, const Constant* CV, bool c } } } else if (isa<UndefValue>(CV)) { - assert(false); + assert(false && "Unlowered UndefValue"); } else { - assert(false); + CV->dump(); + assert(false && "Unsupported constant kind"); } } @@ -2110,6 +2120,7 @@ void JSWriter::printModule(const std::string& fname, bool JSWriter::runOnModule(Module &M) { TheModule = &M; + DL = &getAnalysis<DataLayout>(); setupCallHandlers(); |