diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-02-14 14:51:06 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-02-14 14:51:06 -0800 |
commit | b3d5de7043272a13341ea7ae0ac176a5782f13a7 (patch) | |
tree | 4f9c9aeab4d4b8aa07a6428e21ceb89552c46d37 /lib/Target/JSBackend/JSBackend.cpp | |
parent | 9c0197b97dc9b5be2132f8e6ebe9737d0d7dd7c1 (diff) | |
parent | 8dd47ed0fe367f1d6c0f7cb404d58b24be8b6f5c (diff) |
Merge pull request #14 from sunfishcode/incoming
Instead of lowering pointers, teach the JSBackend how to handle them
Diffstat (limited to 'lib/Target/JSBackend/JSBackend.cpp')
-rw-r--r-- | lib/Target/JSBackend/JSBackend.cpp | 84 |
1 files changed, 48 insertions, 36 deletions
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index 0d83a6a319..dc2404866a 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -30,6 +30,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" @@ -303,7 +304,7 @@ namespace { } std::string getPtrAsStr(const Value* Ptr) { Ptr = Ptr->stripPointerCasts(); - if (isa<const ConstantPointerNull>(Ptr)) return "0"; + if (isa<const ConstantPointerNull>(Ptr) || isa<UndefValue>(Ptr)) return "0"; if (const Function *F = dyn_cast<Function>(Ptr)) { return utostr(getFunctionIndex(F)); } else if (const Constant *CV = dyn_cast<Constant>(Ptr)) { @@ -344,13 +345,13 @@ namespace { void printType(Type* Ty); void printTypes(const Module* M); - std::string getAssign(const StringRef &, const Type *); - std::string getCast(const StringRef &, const Type *, AsmCast sign=ASM_SIGNED); - std::string getParenCast(const StringRef &, const Type *, AsmCast sign=ASM_SIGNED); + std::string getAssign(const StringRef &, Type *); + std::string getCast(const StringRef &, Type *, AsmCast sign=ASM_SIGNED); + std::string getParenCast(const StringRef &, Type *, AsmCast sign=ASM_SIGNED); std::string getDoubleToInt(const StringRef &); std::string getIMul(const Value *, const Value *); - std::string getLoad(const Instruction *I, const Value *P, const Type *T, unsigned Alignment, char sep=';'); - std::string getStore(const Instruction *I, const Value *P, const Type *T, const std::string& VS, unsigned Alignment, char sep=';'); + std::string getLoad(const Instruction *I, const Value *P, Type *T, unsigned Alignment, char sep=';'); + std::string getStore(const Instruction *I, const Value *P, Type *T, const std::string& VS, unsigned Alignment, char sep=';'); void printFunctionBody(const Function *F); bool generateSIMDInstruction(const std::string &iName, const Instruction *I, raw_string_ostream& Code); @@ -485,12 +486,12 @@ const std::string &JSWriter::getJSName(const Value* val) { return ValueNames[val] = name; } -std::string JSWriter::getAssign(const StringRef &s, const Type *t) { +std::string JSWriter::getAssign(const StringRef &s, Type *t) { UsedVars[s] = t->getTypeID(); return (s + " = ").str(); } -std::string JSWriter::getCast(const StringRef &s, const Type *t, AsmCast sign) { +std::string JSWriter::getCast(const StringRef &s, Type *t, AsmCast sign) { switch (t->getTypeID()) { default: { // some types we cannot cast, like vectors - ignore @@ -517,11 +518,12 @@ std::string JSWriter::getCast(const StringRef &s, const Type *t, AsmCast sign) { default: llvm_unreachable("Unsupported integer cast bitwidth"); } } - case Type::PointerTyID: return (s + "|0").str(); + case Type::PointerTyID: + return (sign == ASM_SIGNED || (sign & ASM_NONSPECIFIC) ? s + "|0" : s + ">>>0").str(); } } -std::string JSWriter::getParenCast(const StringRef &s, const Type *t, AsmCast sign) { +std::string JSWriter::getParenCast(const StringRef &s, Type *t, AsmCast sign) { return getCast(("(" + s + ")").str(), t, sign); } @@ -555,15 +557,28 @@ std::string JSWriter::getIMul(const Value *V1, const Value *V2) { return "Math_imul(" + getValueAsStr(V1) + ", " + getValueAsStr(V2) + ")|0"; // unknown or too large, emit imul } -std::string JSWriter::getLoad(const Instruction *I, const Value *P, const Type *T, unsigned Alignment, char sep) { +// Test whether the given value is known to be a null pointer. +static bool isAbsolute(const Value *P) { + if (const IntToPtrInst *ITP = dyn_cast<IntToPtrInst>(P)) { + return isa<ConstantInt>(ITP->getOperand(0)); + } + + if (isa<ConstantPointerNull>(P)) { + return true; + } + + return false; +} + +std::string JSWriter::getLoad(const Instruction *I, const Value *P, Type *T, unsigned Alignment, char sep) { std::string Assign = getAssign(getJSName(I), I->getType()); unsigned Bytes = T->getPrimitiveSizeInBits()/8; std::string text; if (Bytes <= Alignment || Alignment == 0) { text = Assign + getPtrLoad(P); - if (const IntToPtrInst *ITP = dyn_cast<IntToPtrInst>(P)) { + if (isAbsolute(P)) { // loads from an absolute constants are either intentional segfaults (int x = *((int*)0)), or code problems - if (isa<ConstantInt>(ITP->getOperand(0))) text += "; abort() /* segfault, load from absolute addr */"; + text += "; abort() /* segfault, load from absolute addr */"; } } else { // unaligned in some manner @@ -605,7 +620,7 @@ std::string JSWriter::getLoad(const Instruction *I, const Value *P, const Type * break; } case 4: { - if (T->isIntegerTy()) { + if (T->isIntegerTy() || T->isPointerTy()) { switch (Alignment) { case 2: { text = Assign + "HEAPU16[" + PS + ">>1]|" + @@ -622,6 +637,7 @@ std::string JSWriter::getLoad(const Instruction *I, const Value *P, const Type * default: assert(0 && "bad 4i store"); } } else { // float + assert(T->isFloatingPointTy()); switch (Alignment) { case 2: { text = "HEAP16[tempDoublePtr>>1]=HEAP16[" + PS + ">>1]" + sep + @@ -652,9 +668,9 @@ std::string JSWriter::getLoad(const Instruction *I, const Value *P, const Type * return text; } -std::string JSWriter::getStore(const Instruction *I, const Value *P, const Type *T, const std::string& VS, unsigned Alignment, char sep) { +std::string JSWriter::getStore(const Instruction *I, const Value *P, Type *T, const std::string& VS, unsigned Alignment, char sep) { assert(sep == ';'); // FIXME when we need that - unsigned Bytes = T->getPrimitiveSizeInBits()/8; + unsigned Bytes = DL->getTypeAllocSize(T); std::string text; if (Bytes <= Alignment || Alignment == 0) { text = getPtrUse(P) + " = " + VS; @@ -699,7 +715,7 @@ std::string JSWriter::getStore(const Instruction *I, const Value *P, const Type break; } case 4: { - if (T->isIntegerTy()) { + if (T->isIntegerTy() || T->isPointerTy()) { switch (Alignment) { case 2: { text = "HEAP16[" + PS + ">>1]=" + VS + "&65535;" + @@ -716,6 +732,7 @@ std::string JSWriter::getStore(const Instruction *I, const Value *P, const Type default: assert(0 && "bad 4i store"); } } else { // float + assert(T->isFloatingPointTy()); text = "HEAPF32[tempDoublePtr>>2]=" + VS + ';'; switch (Alignment) { case 2: { @@ -773,7 +790,7 @@ std::string JSWriter::getHeapAccess(const std::string& Name, unsigned Bytes, boo std::string JSWriter::getPtrUse(const Value* Ptr) { Type *t = cast<PointerType>(Ptr->getType())->getElementType(); - unsigned Bytes = t->getPrimitiveSizeInBits()/8; + unsigned Bytes = DL->getTypeAllocSize(t); if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) { std::string text = ""; unsigned Addr = getGlobalAddress(GV->getName().str()); @@ -781,9 +798,10 @@ std::string JSWriter::getPtrUse(const Value* Ptr) { default: llvm_unreachable("Unsupported type"); case 8: return "HEAPF64[" + utostr(Addr >> 3) + "]"; case 4: { - if (t->isIntegerTy()) { + if (t->isIntegerTy() || t->isPointerTy()) { return "HEAP32[" + utostr(Addr >> 2) + "]"; } else { + assert(t->isFloatingPointTy()); return "HEAPF32[" + utostr(Addr >> 2) + "]"; } } @@ -791,7 +809,7 @@ std::string JSWriter::getPtrUse(const Value* Ptr) { case 1: return "HEAP8[" + utostr(Addr) + "]"; } } else { - return getHeapAccess(getOpName(Ptr), Bytes, t->isIntegerTy()); + return getHeapAccess(getPtrAsStr(Ptr), Bytes, t->isIntegerTy() || t->isPointerTy()); } } @@ -870,7 +888,7 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) { } return CI->getValue().toString(10, sign != ASM_UNSIGNED); } else if (isa<UndefValue>(CV)) { - return CV->getType()->isIntegerTy() ? "0" : getCast("0", CV->getType()); + return CV->getType()->isIntegerTy() || CV->getType()->isPointerTy() ? "0" : getCast("0", CV->getType()); } else if (isa<ConstantAggregateZero>(CV)) { if (VectorType *VT = dyn_cast<VectorType>(CV->getType())) { if (VT->getElementType()->isIntegerTy()) { @@ -1266,18 +1284,12 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod } Type *T = AI->getAllocatedType(); std::string Size; - if (T->isVectorTy()) { - checkVectorType(T); - Size = "16"; + uint64_t BaseSize = DL->getTypeAllocSize(T); + const Value *AS = AI->getArraySize(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(AS)) { + Size = Twine(memAlign(BaseSize * CI->getZExtValue())).str(); } else { - assert(!isa<ArrayType>(T)); - const Value *AS = AI->getArraySize(); - unsigned BaseSize = T->getScalarSizeInBits()/8; - if (const ConstantInt *CI = dyn_cast<ConstantInt>(AS)) { - Size = Twine(memAlign(BaseSize * CI->getZExtValue())).str(); - } else { - Size = memAlignStr("((" + utostr(BaseSize) + '*' + getValueAsStr(AS) + ")|0)"); - } + Size = memAlignStr("((" + utostr(BaseSize) + '*' + getValueAsStr(AS) + ")|0)"); } Code << getAssign(iName, Type::getInt32Ty(I->getContext())) << "STACKTOP; STACKTOP = STACKTOP + " << Size << "|0;"; break; @@ -1556,8 +1568,8 @@ void JSWriter::printFunctionBody(const Function *F) { R.Render(); // Emit local variables - UsedVars["sp"] = Type::getInt32Ty(F->getContext())->getTypeID(); - UsedVars["label"] = Type::getInt32Ty(F->getContext())->getTypeID(); + UsedVars["sp"] = Type::IntegerTyID; + UsedVars["label"] = Type::IntegerTyID; if (!UsedVars.empty()) { unsigned Count = 0; for (VarMap::const_iterator VI = UsedVars.begin(); VI != UsedVars.end(); ++VI) { @@ -1670,9 +1682,8 @@ void JSWriter::printFunction(const Function *F) { if (const AllocaInst* AI = dyn_cast<AllocaInst>(II)) { Type *T = AI->getAllocatedType(); if (!T->isVectorTy()) { - assert(!isa<ArrayType>(T)); const Value *AS = AI->getArraySize(); - unsigned BaseSize = T->getScalarSizeInBits()/8; + unsigned BaseSize = DL->getTypeAllocSize(T); if (const ConstantInt *CI = dyn_cast<ConstantInt>(AS)) { // TODO: group by alignment to avoid unnecessary padding unsigned Size = memAlign(BaseSize * CI->getZExtValue()); @@ -2072,6 +2083,7 @@ void JSWriter::calculateNativizedVars(const Function *F) { const Instruction *I = &*II; if (const AllocaInst *AI = dyn_cast<const AllocaInst>(I)) { if (AI->getAllocatedType()->isVectorTy()) continue; // we do not nativize vectors, we rely on the LLVM optimizer to avoid load/stores on them + if (AI->getAllocatedType()->isAggregateType()) continue; // we do not nativize aggregates either // this is on the stack. if its address is never used nor escaped, we can nativize it bool Fail = false; for (Instruction::const_use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE && !Fail; ++UI) { |