From 076d37969873de21057991b03d901d31c58039e3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Feb 2014 18:30:40 -0800 Subject: Handle ConstantPointerNull correctly in more places. --- lib/Target/JSBackend/JSBackend.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'lib/Target/JSBackend/JSBackend.cpp') diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index 0d83a6a319..ac1fdfed10 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -555,15 +555,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 } +// Test whether the given value is known to be a null pointer. +static bool isAbsolute(const Value *P) { + if (const IntToPtrInst *ITP = dyn_cast(P)) { + return isa(ITP->getOperand(0)); + } + + if (isa(P)) { + return true; + } + + return false; +} + std::string JSWriter::getLoad(const Instruction *I, const Value *P, const 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(P)) { + if (isAbsolute(P)) { // loads from an absolute constants are either intentional segfaults (int x = *((int*)0)), or code problems - if (isa(ITP->getOperand(0))) text += "; abort() /* segfault, load from absolute addr */"; + text += "; abort() /* segfault, load from absolute addr */"; } } else { // unaligned in some manner @@ -791,7 +804,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()); } } -- cgit v1.2.3-70-g09d2 From 4875328877ab82284e108c6c858ffba929cf8488 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Feb 2014 18:33:01 -0800 Subject: Respect the requested signedness for pointer values. --- lib/Target/JSBackend/JSBackend.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/Target/JSBackend/JSBackend.cpp') diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index ac1fdfed10..5c2d94012e 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -517,7 +517,8 @@ 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(); } } -- cgit v1.2.3-70-g09d2 From 35c77715ea2991eaf0b433ec48d9e43ec54c0269 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Feb 2014 18:33:37 -0800 Subject: Use DataLayout to determine type size. getPrimitiveSizeInBits works on integer types but not on pointer types. This change makes the code more robust, and will help support the removal of the pointer lowering pass. This also requires removing const from some Type pointers. Types are immutable, so the convention is that const is redundant. --- lib/Target/JSBackend/JSBackend.cpp | 43 ++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 25 deletions(-) (limited to 'lib/Target/JSBackend/JSBackend.cpp') diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index 5c2d94012e..fa6c999a7a 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -344,13 +344,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 +485,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 @@ -522,7 +522,7 @@ std::string JSWriter::getCast(const StringRef &s, const Type *t, AsmCast sign) { } } -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); } @@ -569,7 +569,7 @@ static bool isAbsolute(const Value *P) { return false; } -std::string JSWriter::getLoad(const Instruction *I, const Value *P, const Type *T, unsigned Alignment, char sep) { +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; @@ -666,9 +666,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; @@ -787,7 +787,7 @@ std::string JSWriter::getHeapAccess(const std::string& Name, unsigned Bytes, boo std::string JSWriter::getPtrUse(const Value* Ptr) { Type *t = cast(Ptr->getType())->getElementType(); - unsigned Bytes = t->getPrimitiveSizeInBits()/8; + unsigned Bytes = DL->getTypeAllocSize(t); if (const GlobalVariable *GV = dyn_cast(Ptr)) { std::string text = ""; unsigned Addr = getGlobalAddress(GV->getName().str()); @@ -1280,18 +1280,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(AS)) { + Size = Twine(memAlign(BaseSize * CI->getZExtValue())).str(); } else { - assert(!isa(T)); - const Value *AS = AI->getArraySize(); - unsigned BaseSize = T->getScalarSizeInBits()/8; - if (const ConstantInt *CI = dyn_cast(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; @@ -1684,9 +1678,8 @@ void JSWriter::printFunction(const Function *F) { if (const AllocaInst* AI = dyn_cast(II)) { Type *T = AI->getAllocatedType(); if (!T->isVectorTy()) { - assert(!isa(T)); const Value *AS = AI->getArraySize(); - unsigned BaseSize = T->getScalarSizeInBits()/8; + unsigned BaseSize = DL->getTypeAllocSize(T); if (const ConstantInt *CI = dyn_cast(AS)) { // TODO: group by alignment to avoid unnecessary padding unsigned Size = memAlign(BaseSize * CI->getZExtValue()); -- cgit v1.2.3-70-g09d2 From a8eadb7743e528ebac52835c7bd95d722bd3c751 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Feb 2014 18:43:37 -0800 Subject: Handle pointer types and ConstantExprs in more places. --- lib/Target/JSBackend/CallHandlers.h | 28 +++++++++------------------- lib/Target/JSBackend/JSBackend.cpp | 16 ++++++++++------ 2 files changed, 19 insertions(+), 25 deletions(-) (limited to 'lib/Target/JSBackend/JSBackend.cpp') diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h index e88b781cb4..4a57bcddc2 100644 --- a/lib/Target/JSBackend/CallHandlers.h +++ b/lib/Target/JSBackend/CallHandlers.h @@ -10,28 +10,18 @@ CallHandlerMap *CallHandlers; // Definitions unsigned getNumArgOperands(const Instruction *I) { - if (const CallInst *CI = dyn_cast(I)) { - return CI->getNumArgOperands(); - } else { - return cast(I)->getNumArgOperands(); - } + return ImmutableCallSite(I).arg_size(); } const Value *getActuallyCalledValue(const Instruction *I) { - const Value *CV = NULL; - if (const CallInst *CI = dyn_cast(I)) { - CV = CI->getCalledValue(); - } else { - CV = cast(I)->getCalledValue(); - } - if (const BitCastInst *B = dyn_cast(CV)) { - // if the called value is a bitcast of a function, then we just call it directly, properly - // for example, extern void x() in C will turn into void x(...) in LLVM IR, then the IR bitcasts - // it to the proper form right before the call. this both causes an unnecessary indirect - // call, and it is done with the wrong type. TODO: don't even put it into the function table - if (const Function *F = dyn_cast(B->getOperand(0))) { - CV = F; - } + const Value *CV = ImmutableCallSite(I).getCalledValue(); + + // if the called value is a bitcast of a function, then we just call it directly, properly + // for example, extern void x() in C will turn into void x(...) in LLVM IR, then the IR bitcasts + // it to the proper form right before the call. this both causes an unnecessary indirect + // call, and it is done with the wrong type. TODO: don't even put it into the function table + if (const Function *F = dyn_cast(CV->stripPointerCasts())) { + CV = F; } return CV; } diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index fa6c999a7a..ea642163e3 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(Ptr)) return "0"; + if (isa(Ptr) || isa(Ptr)) return "0"; if (const Function *F = dyn_cast(Ptr)) { return utostr(getFunctionIndex(F)); } else if (const Constant *CV = dyn_cast(Ptr)) { @@ -619,7 +620,7 @@ std::string JSWriter::getLoad(const Instruction *I, const Value *P, Type *T, uns break; } case 4: { - if (T->isIntegerTy()) { + if (T->isIntegerTy() || T->isPointerTy()) { switch (Alignment) { case 2: { text = Assign + "HEAPU16[" + PS + ">>1]|" + @@ -636,6 +637,7 @@ std::string JSWriter::getLoad(const Instruction *I, const Value *P, Type *T, uns default: assert(0 && "bad 4i store"); } } else { // float + assert(T->isFloatingPointTy()); switch (Alignment) { case 2: { text = "HEAP16[tempDoublePtr>>1]=HEAP16[" + PS + ">>1]" + sep + @@ -713,7 +715,7 @@ std::string JSWriter::getStore(const Instruction *I, const Value *P, Type *T, co break; } case 4: { - if (T->isIntegerTy()) { + if (T->isIntegerTy() || T->isPointerTy()) { switch (Alignment) { case 2: { text = "HEAP16[" + PS + ">>1]=" + VS + "&65535;" + @@ -730,6 +732,7 @@ std::string JSWriter::getStore(const Instruction *I, const Value *P, Type *T, co default: assert(0 && "bad 4i store"); } } else { // float + assert(T->isFloatingPointTy()); text = "HEAPF32[tempDoublePtr>>2]=" + VS + ';'; switch (Alignment) { case 2: { @@ -795,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) + "]"; } } @@ -805,7 +809,7 @@ std::string JSWriter::getPtrUse(const Value* Ptr) { case 1: return "HEAP8[" + utostr(Addr) + "]"; } } else { - return getHeapAccess(getPtrAsStr(Ptr), Bytes, t->isIntegerTy()); + return getHeapAccess(getPtrAsStr(Ptr), Bytes, t->isIntegerTy() || t->isPointerTy()); } } @@ -884,7 +888,7 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) { } return CI->getValue().toString(10, sign != ASM_UNSIGNED); } else if (isa(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(CV)) { if (VectorType *VT = dyn_cast(CV->getType())) { if (VT->getElementType()->isIntegerTy()) { -- cgit v1.2.3-70-g09d2 From 8e79a39877f2127481a0c31b8c310353330daeae Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 14 Feb 2014 11:37:06 -0800 Subject: Don't try to nativize aggregate allocas. --- lib/Target/JSBackend/JSBackend.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/Target/JSBackend/JSBackend.cpp') diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index ea642163e3..b204026ff0 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -2083,6 +2083,7 @@ void JSWriter::calculateNativizedVars(const Function *F) { const Instruction *I = &*II; if (const AllocaInst *AI = dyn_cast(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) { -- cgit v1.2.3-70-g09d2 From 7db0b92aeaf21b8e49bb3b02ba43d61a114cbcf5 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 14 Feb 2014 11:35:50 -0800 Subject: Minor code simplification. --- lib/Target/JSBackend/JSBackend.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/Target/JSBackend/JSBackend.cpp') diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index b204026ff0..dc2404866a 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -1568,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) { -- cgit v1.2.3-70-g09d2