aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/JSBackend/JSBackend.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-02-13 10:57:20 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-02-13 10:57:20 -0800
commit04faad37ba15e237c87e58e9914a998a3d7a2ed1 (patch)
treea7c10dbce5f13c4badecacd1f6de052606b354ae /lib/Target/JSBackend/JSBackend.cpp
parent08cdac187ad3a109d5e68c771ca2b2d2e23d9e3f (diff)
parent718e02f4cea34a6f34d7a6f1f82411960bff1ba4 (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.cpp143
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();