aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/JSBackend/JSBackend.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-02-14 14:51:06 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-02-14 14:51:06 -0800
commitb3d5de7043272a13341ea7ae0ac176a5782f13a7 (patch)
tree4f9c9aeab4d4b8aa07a6428e21ceb89552c46d37 /lib/Target/JSBackend/JSBackend.cpp
parent9c0197b97dc9b5be2132f8e6ebe9737d0d7dd7c1 (diff)
parent8dd47ed0fe367f1d6c0f7cb404d58b24be8b6f5c (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.cpp84
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) {