aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/JSBackend/JSBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/JSBackend/JSBackend.cpp')
-rw-r--r--lib/Target/JSBackend/JSBackend.cpp231
1 files changed, 134 insertions, 97 deletions
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp
index fccdb52bf7..75e4a1a5e7 100644
--- a/lib/Target/JSBackend/JSBackend.cpp
+++ b/lib/Target/JSBackend/JSBackend.cpp
@@ -50,7 +50,7 @@ using namespace llvm;
#define dump(x) fprintf(stderr, x "\n")
#define dumpv(x, ...) fprintf(stderr, x "\n", __VA_ARGS__)
-#define dumpfail(x) { fprintf(stderr, x "\n"); fprintf(stderr, "%s : %d\n", __FILE__, __LINE__); report_fatal_error("fail"); }
+#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; \
@@ -217,7 +217,7 @@ namespace {
else if (T->isFloatTy() || T->isDoubleTy()) return 'd'; // TODO: float
else return 'i';
}
- std::string getFunctionSignature(const FunctionType *F, std::string *Name=NULL) {
+ std::string getFunctionSignature(const FunctionType *F, const std::string *Name=NULL) {
if (Name) {
// special-case some function signatures, because of how we emit code for them FIXME this is hackish
if (*Name == "_llvm_memcpy_p0i8_p0i8_i32" || *Name == "_memcpy" ||
@@ -235,7 +235,7 @@ namespace {
return Ret;
}
unsigned getFunctionIndex(const Function *F) {
- std::string Name = getJSName(F);
+ const std::string &Name = getJSName(F);
if (IndexedFunctions.find(Name) != IndexedFunctions.end()) return IndexedFunctions[Name];
std::string Sig = getFunctionSignature(F->getFunctionType(), &Name);
FunctionTable &Table = FunctionTables[Sig];
@@ -310,7 +310,7 @@ namespace {
std::string getValueAsParenStr(const Value*);
std::string getValueAsCastParenStr(const Value*, AsmCast sign=ASM_SIGNED);
- std::string getJSName(const Value* val);
+ const std::string &getJSName(const Value* val);
std::string getPhiCode(const BasicBlock *From, const BasicBlock *To);
@@ -381,7 +381,7 @@ std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) {
int index = P->getBasicBlockIndex(From);
if (index < 0) continue;
// we found it
- std::string name = getJSName(P);
+ const std::string &name = getJSName(P);
assigns[name] = getAssign(name, P->getType());
Value *V = P->getIncomingValue(index);
values[name] = V;
@@ -424,12 +424,12 @@ std::string JSWriter::getPhiCode(const BasicBlock *From, const BasicBlock *To) {
return pre + post;
}
-std::string JSWriter::getJSName(const Value* val) {
- std::string name;
+const std::string &JSWriter::getJSName(const Value* val) {
ValueMap::iterator I = ValueNames.find(val);
if (I != ValueNames.end() && I->first == val)
return I->second;
+ std::string name;
if (val->hasName()) {
if (isa<Function>(val) || isa<Constant>(val)) {
name = std::string("_") + val->getName().str();
@@ -875,30 +875,37 @@ bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instructi
switch (I->getOpcode()) {
default: dumpIR(I); error("invalid vector instr"); break;
- case Instruction::FAdd: Code << "SIMD.float32x4.add(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break;
- case Instruction::FSub: Code << "SIMD.float32x4.sub(" + 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;
- case Instruction::Add: Code << "SIMD.int32x4.add(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break;
- case Instruction::Sub: Code << "SIMD.int32x4.sub(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break;
- case Instruction::Mul: Code << "SIMD.int32x4.mul(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break;
- case Instruction::And: Code << "SIMD.int32x4.and(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break;
- case Instruction::Or: Code << "SIMD.int32x4.or(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; break;
- case Instruction::Xor: Code << "SIMD.int32x4.xor(" + getValueAsStr(I->getOperand(0)) + "," + getValueAsStr(I->getOperand(1)) + ")"; 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;
+ case Instruction::Add: Code << "SIMD.int32x4.add(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case Instruction::Sub: Code << "SIMD.int32x4.sub(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case Instruction::Mul: Code << "SIMD.int32x4.mul(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case Instruction::And: Code << "SIMD.int32x4.and(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case Instruction::Or: Code << "SIMD.int32x4.or(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case Instruction::Xor: Code << "SIMD.int32x4.xor(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case Instruction::FSub:
+ // LLVM represents an fneg(x) as -0.0 - x.
+ if (BinaryOperator::isFNeg(I)) {
+ Code << "SIMD.float32x4.neg(" << getValueAsStr(BinaryOperator::getFNegArgument(I)) << ")";
+ } else {
+ Code << "SIMD.float32x4.sub(" << getValueAsStr(I->getOperand(0)) << "," << getValueAsStr(I->getOperand(1)) << ")";
+ }
+ break;
case Instruction::BitCast: {
if (cast<VectorType>(I->getType())->getElementType()->isIntegerTy()) {
- Code << "SIMD.float32x4.bitsToInt32x4(" + getValueAsStr(I->getOperand(0)) + ')';
+ Code << "SIMD.float32x4.bitsToInt32x4(" << getValueAsStr(I->getOperand(0)) << ')';
} else {
- Code << "SIMD.int32x4.bitsToInt32x4(" + getValueAsStr(I->getOperand(0)) + ')';
+ Code << "SIMD.int32x4.bitsToInt32x4(" << getValueAsStr(I->getOperand(0)) << ')';
}
break;
}
case Instruction::Load: {
std::string PS = getOpName(I->getOperand(0));
if (VT->getElementType()->isIntegerTy()) {
- Code << "int32x4(HEAPU32[" + PS + ">>2],HEAPU32[" + PS + "+4>>2],HEAPU32[" + PS + "+8>>2],HEAPU32[" + PS + "+12>>2])";
+ Code << "int32x4(HEAPU32[" << PS << ">>2],HEAPU32[" << PS << "+4>>2],HEAPU32[" << PS << "+8>>2],HEAPU32[" << PS << "+12>>2])";
} else {
- Code << "float32x4(HEAPF32[" + PS + ">>2],HEAPF32[" + PS + "+4>>2],HEAPF32[" + PS + "+8>>2],HEAPF32[" + PS + "+12>>2])";
+ Code << "float32x4(HEAPF32[" << PS << ">>2],HEAPF32[" << PS << "+4>>2],HEAPF32[" << PS << "+8>>2],HEAPF32[" << PS << "+12>>2])";
}
break;
}
@@ -913,7 +920,7 @@ bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instructi
Code << "SIMD.float32x4.with";
}
Code << SIMDLane[Index];
- Code << "(" + getValueAsStr(III->getOperand(0)) + ',' + getValueAsStr(III->getOperand(1)) + ')';
+ Code << "(" << getValueAsStr(III->getOperand(0)) << ',' << getValueAsStr(III->getOperand(1)) << ')';
break;
}
case Instruction::ShuffleVector: {
@@ -930,10 +937,10 @@ bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instructi
if (Mask < 0) {
Code << "0";
} else if (Mask < 4) {
- Code << A + "." + simdLane[Mask];
+ Code << A << "." << simdLane[Mask];
} else {
assert(Mask < 8);
- Code << B + "." + simdLane[Mask-4];
+ Code << B << "." << simdLane[Mask-4];
}
if (i < 3) Code << ",";
}
@@ -949,9 +956,9 @@ bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instructi
std::string PS = getOpName(I->getOperand(1));
std::string VS = getValueAsStr(I->getOperand(0));
if (VT->getElementType()->isIntegerTy()) {
- Code << "HEAPU32[" + PS + ">>2]=" + VS + ".x;HEAPU32[" + PS + "+4>>2]=" + VS + ".y;HEAPU32[" + PS + "+8>>2]=" + VS + ".z;HEAPU32[" + PS + "+12>>2]=" + VS + ".w";
+ Code << "HEAPU32[" << PS << ">>2]=" << VS << ".x;HEAPU32[" << PS << "+4>>2]=" << VS << ".y;HEAPU32[" << PS << "+8>>2]=" << VS << ".z;HEAPU32[" << PS << "+12>>2]=" << VS << ".w";
} else {
- Code << "HEAPF32[" + PS + ">>2]=" + VS + ".x;HEAPF32[" + PS + "+4>>2]=" + VS + ".y;HEAPF32[" + PS + "+8>>2]=" + VS + ".z;HEAPF32[" + PS + "+12>>2]=" + VS + ".w";
+ Code << "HEAPF32[" << PS << ">>2]=" << VS << ".x;HEAPF32[" << PS << "+4>>2]=" << VS << ".y;HEAPF32[" << PS << "+8>>2]=" << VS << ".z;HEAPF32[" << PS << "+12>>2]=" << VS << ".w";
}
return true;
} else if (I->getOpcode() == Instruction::ExtractElement) {
@@ -962,20 +969,20 @@ bool JSWriter::generateSIMDInstruction(const std::string &iName, const Instructi
unsigned Index = IndexInt->getZExtValue();
assert(Index <= 3);
Code << getAssign(iName, I->getType());
- Code << getValueAsStr(EEI->getVectorOperand()) + '.' + simdLane[Index];
+ Code << getValueAsStr(EEI->getVectorOperand()) << '.' << simdLane[Index];
return true;
}
}
return false;
}
-uint64_t LSBMask(unsigned numBits) {
+static uint64_t LSBMask(unsigned numBits) {
return numBits >= 64 ? 0xFFFFFFFFFFFFFFFFULL : (1ULL << numBits) - 1;
}
// generateInstruction - This member is called for each Instruction in a function.
void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Code) {
- std::string iName(getJSName(I));
+ const std::string &iName(getJSName(I));
Type *T = I->getType();
if (T->isIntegerTy() && T->getIntegerBitWidth() > 32) {
@@ -997,7 +1004,7 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
if (RV == NULL) {
Code << ";";
} else {
- Code << " " + getValueAsCastStr(RV, ASM_NONSPECIFIC) + ";";
+ Code << " " << getValueAsCastStr(RV, ASM_NONSPECIFIC) << ";";
}
break;
}
@@ -1045,14 +1052,14 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::URem:
- case Instruction::SRem: Code << "(" +
- getValueAsCastParenStr(I->getOperand(0), (opcode == Instruction::SDiv || opcode == Instruction::SRem) ? ASM_SIGNED : ASM_UNSIGNED) +
- ((opcode == Instruction::UDiv || opcode == Instruction::SDiv) ? " / " : " % ") +
- getValueAsCastParenStr(I->getOperand(1), (opcode == Instruction::SDiv || opcode == Instruction::SRem) ? ASM_SIGNED : ASM_UNSIGNED) +
+ case Instruction::SRem: Code << "(" <<
+ getValueAsCastParenStr(I->getOperand(0), (opcode == Instruction::SDiv || opcode == Instruction::SRem) ? ASM_SIGNED : ASM_UNSIGNED) <<
+ ((opcode == Instruction::UDiv || opcode == Instruction::SDiv) ? " / " : " % ") <<
+ getValueAsCastParenStr(I->getOperand(1), (opcode == Instruction::SDiv || opcode == Instruction::SRem) ? ASM_SIGNED : ASM_UNSIGNED) <<
")&-1"; break;
- case Instruction::And: Code << getValueAsStr(I->getOperand(0)) + " & " + getValueAsStr(I->getOperand(1)); break;
- case Instruction::Or: Code << getValueAsStr(I->getOperand(0)) + " | " + getValueAsStr(I->getOperand(1)); break;
- case Instruction::Xor: Code << getValueAsStr(I->getOperand(0)) + " ^ " + getValueAsStr(I->getOperand(1)); break;
+ case Instruction::And: Code << getValueAsStr(I->getOperand(0)) << " & " << getValueAsStr(I->getOperand(1)); break;
+ case Instruction::Or: Code << getValueAsStr(I->getOperand(0)) << " | " << getValueAsStr(I->getOperand(1)); break;
+ case Instruction::Xor: Code << getValueAsStr(I->getOperand(0)) << " ^ " << getValueAsStr(I->getOperand(1)); break;
case Instruction::Shl: {
std::string Shifted = getValueAsStr(I->getOperand(0)) + " << " + getValueAsStr(I->getOperand(1));
if (I->getType()->getIntegerBitWidth() < 32) {
@@ -1067,14 +1074,21 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
if (I->getType()->getIntegerBitWidth() < 32) {
Input = '(' + getCast(Input, I->getType(), opcode == Instruction::AShr ? ASM_SIGNED : ASM_UNSIGNED) + ')'; // fill in high bits, as shift needs those and is done in 32-bit
}
- Code << Input + (opcode == Instruction::AShr ? " >> " : " >>> ") + getValueAsStr(I->getOperand(1));
+ Code << Input << (opcode == Instruction::AShr ? " >> " : " >>> ") << getValueAsStr(I->getOperand(1));
break;
}
- case Instruction::FAdd: Code << getValueAsStr(I->getOperand(0)) + " + " + getValueAsStr(I->getOperand(1)); break; // TODO: ensurefloat here
- case Instruction::FSub: Code << getValueAsStr(I->getOperand(0)) + " - " + getValueAsStr(I->getOperand(1)); break;
- case Instruction::FMul: Code << getValueAsStr(I->getOperand(0)) + " * " + getValueAsStr(I->getOperand(1)); break;
- case Instruction::FDiv: Code << getValueAsStr(I->getOperand(0)) + " / " + getValueAsStr(I->getOperand(1)); break;
- case Instruction::FRem: Code << getValueAsStr(I->getOperand(0)) + " % " + getValueAsStr(I->getOperand(1)); break;
+ case Instruction::FAdd: Code << getValueAsStr(I->getOperand(0)) << " + " << getValueAsStr(I->getOperand(1)); break; // TODO: ensurefloat here
+ case Instruction::FMul: Code << getValueAsStr(I->getOperand(0)) << " * " << getValueAsStr(I->getOperand(1)); break;
+ case Instruction::FDiv: Code << getValueAsStr(I->getOperand(0)) << " / " << getValueAsStr(I->getOperand(1)); break;
+ case Instruction::FRem: Code << getValueAsStr(I->getOperand(0)) << " % " << getValueAsStr(I->getOperand(1)); break;
+ case Instruction::FSub:
+ // LLVM represents an fneg(x) as -0.0 - x.
+ if (BinaryOperator::isFNeg(I)) {
+ Code << "-" << getValueAsStr(BinaryOperator::getFNegArgument(I));
+ } else {
+ Code << getValueAsStr(I->getOperand(0)) << " - " << getValueAsStr(I->getOperand(1));
+ }
+ break;
default: error("bad icmp"); break;
}
Code << ';';
@@ -1083,24 +1097,50 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
case Instruction::FCmp: {
Code << getAssign(iName, I->getType());
switch (cast<FCmpInst>(I)->getPredicate()) {
- case FCmpInst::FCMP_OEQ:
- case FCmpInst::FCMP_UEQ: Code << getValueAsStr(I->getOperand(0)) + " == " + getValueAsStr(I->getOperand(1)); break;
+ // Comparisons which are simple JS operators.
+ case FCmpInst::FCMP_OEQ: Code << getValueAsStr(I->getOperand(0)) << " == " << getValueAsStr(I->getOperand(1)); break;
+ case FCmpInst::FCMP_UNE: Code << getValueAsStr(I->getOperand(0)) << " != " << getValueAsStr(I->getOperand(1)); break;
+ case FCmpInst::FCMP_OGT: Code << getValueAsStr(I->getOperand(0)) << " > " << getValueAsStr(I->getOperand(1)); break;
+ case FCmpInst::FCMP_OGE: Code << getValueAsStr(I->getOperand(0)) << " >= " << getValueAsStr(I->getOperand(1)); break;
+ case FCmpInst::FCMP_OLT: Code << getValueAsStr(I->getOperand(0)) << " < " << getValueAsStr(I->getOperand(1)); break;
+ case FCmpInst::FCMP_OLE: Code << getValueAsStr(I->getOperand(0)) << " <= " << getValueAsStr(I->getOperand(1)); break;
+
+ // Comparisons which are inverses of JS operators.
+ case FCmpInst::FCMP_UGT:
+ Code << "!(" << getValueAsStr(I->getOperand(0)) << " <= " << getValueAsStr(I->getOperand(1)) << ")";
+ break;
+ case FCmpInst::FCMP_UGE:
+ Code << "!(" << getValueAsStr(I->getOperand(0)) << " < " << getValueAsStr(I->getOperand(1)) << ")";
+ break;
+ case FCmpInst::FCMP_ULT:
+ Code << "!(" << getValueAsStr(I->getOperand(0)) << " >= " << getValueAsStr(I->getOperand(1)) << ")";
+ break;
+ case FCmpInst::FCMP_ULE:
+ Code << "!(" << getValueAsStr(I->getOperand(0)) << " > " << getValueAsStr(I->getOperand(1)) << ")";
+ break;
+
+ // Comparisons which require explicit NaN checks.
+ case FCmpInst::FCMP_UEQ:
+ Code << "(" << getValueAsStr(I->getOperand(0)) << " != " << getValueAsStr(I->getOperand(0)) << ") | " <<
+ "(" << getValueAsStr(I->getOperand(1)) << " != " << getValueAsStr(I->getOperand(1)) << ") |" <<
+ "(" << getValueAsStr(I->getOperand(0)) << " == " << getValueAsStr(I->getOperand(1)) << ")";
+ break;
case FCmpInst::FCMP_ONE:
- case FCmpInst::FCMP_UNE: Code << getValueAsStr(I->getOperand(0)) + " != " + getValueAsStr(I->getOperand(1)); break;
- case FCmpInst::FCMP_OGT:
- case FCmpInst::FCMP_UGT: Code << getValueAsStr(I->getOperand(0)) + " > " + getValueAsStr(I->getOperand(1)); break;
- case FCmpInst::FCMP_OGE:
- case FCmpInst::FCMP_UGE: Code << getValueAsStr(I->getOperand(0)) + " >= " + getValueAsStr(I->getOperand(1)); break;
- case FCmpInst::FCMP_OLT:
- case FCmpInst::FCMP_ULT: Code << getValueAsStr(I->getOperand(0)) + " < " + getValueAsStr(I->getOperand(1)); break;
- case FCmpInst::FCMP_OLE:
- case FCmpInst::FCMP_ULE: Code << getValueAsStr(I->getOperand(0)) + " <= " + getValueAsStr(I->getOperand(1)); break;
- case FCmpInst::FCMP_ORD: Code << "(" + getValueAsStr(I->getOperand(0)) + " == " + getValueAsStr(I->getOperand(0)) + ") & " +
- "(" + getValueAsStr(I->getOperand(1)) + " == " + getValueAsStr(I->getOperand(1)) + ")"; break;
- case FCmpInst::FCMP_UNO: Code << "(" + getValueAsStr(I->getOperand(0)) + " != " + getValueAsStr(I->getOperand(0)) + ") | " +
- "(" + getValueAsStr(I->getOperand(1)) + " != " + getValueAsStr(I->getOperand(1)) + ")"; break;
+ Code << "(" << getValueAsStr(I->getOperand(0)) << " == " << getValueAsStr(I->getOperand(0)) << ") & " <<
+ "(" << getValueAsStr(I->getOperand(1)) << " == " << getValueAsStr(I->getOperand(1)) << ") &" <<
+ "(" << getValueAsStr(I->getOperand(0)) << " != " << getValueAsStr(I->getOperand(1)) << ")";
+ break;
+
+ // Simple NaN checks.
+ case FCmpInst::FCMP_ORD: Code << "(" << getValueAsStr(I->getOperand(0)) << " == " << getValueAsStr(I->getOperand(0)) << ") & " <<
+ "(" << getValueAsStr(I->getOperand(1)) << " == " << getValueAsStr(I->getOperand(1)) << ")"; break;
+ case FCmpInst::FCMP_UNO: Code << "(" << getValueAsStr(I->getOperand(0)) << " != " << getValueAsStr(I->getOperand(0)) << ") | " <<
+ "(" << getValueAsStr(I->getOperand(1)) << " != " << getValueAsStr(I->getOperand(1)) << ")"; break;
+
+ // Simple constants.
case FCmpInst::FCMP_FALSE: Code << "0"; break;
case FCmpInst::FCMP_TRUE : Code << "1"; break;
+
default: error("bad fcmp"); break;
}
Code << ";";
@@ -1108,12 +1148,9 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
}
case Instruction::ICmp: {
unsigned predicate = cast<ICmpInst>(I)->getPredicate();
- AsmCast sign = (predicate == ICmpInst::ICMP_ULE ||
- predicate == ICmpInst::ICMP_UGE ||
- predicate == ICmpInst::ICMP_ULT ||
- predicate == ICmpInst::ICMP_UGT) ? ASM_UNSIGNED : ASM_SIGNED;
- Code << getAssign(iName, Type::getInt32Ty(I->getContext())) + "(" +
- getValueAsCastStr(I->getOperand(0), sign) +
+ AsmCast sign = CmpInst::isUnsigned(predicate) ? ASM_UNSIGNED : ASM_SIGNED;
+ Code << getAssign(iName, Type::getInt32Ty(I->getContext())) << "(" <<
+ getValueAsCastStr(I->getOperand(0), sign) <<
")";
switch (predicate) {
case ICmpInst::ICMP_EQ: Code << "=="; break;
@@ -1128,8 +1165,8 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
case ICmpInst::ICMP_SGT: Code << ">"; break;
default: assert(0);
}
- Code << "(" +
- getValueAsCastStr(I->getOperand(1), sign) +
+ Code << "(" <<
+ getValueAsCastStr(I->getOperand(1), sign) <<
");";
break;
}
@@ -1155,7 +1192,7 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
Size = memAlignStr("((" + utostr(BaseSize) + '*' + getValueAsStr(AS) + ")|0)");
}
}
- Code << getAssign(iName, Type::getInt32Ty(I->getContext())) + "STACKTOP; STACKTOP = STACKTOP + " + Size + "|0;";
+ Code << getAssign(iName, Type::getInt32Ty(I->getContext())) << "STACKTOP; STACKTOP = STACKTOP + " << Size << "|0;";
break;
}
case Instruction::Load: {
@@ -1164,9 +1201,9 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
unsigned Alignment = LI->getAlignment();
std::string Assign = getAssign(iName, LI->getType());
if (NativizedVars.count(P)) {
- Code << Assign + getValueAsStr(P) + ';';
+ Code << Assign << getValueAsStr(P) << ';';
} else {
- Code << getLoad(Assign, P, LI->getType(), Alignment) + ';';
+ Code << getLoad(Assign, P, LI->getType(), Alignment) << ';';
}
break;
}
@@ -1177,9 +1214,9 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
unsigned Alignment = SI->getAlignment();
std::string VS = getValueAsStr(V);
if (NativizedVars.count(P)) {
- Code << getValueAsStr(P) + " = " + VS + ';';
+ Code << getValueAsStr(P) << " = " << VS << ';';
} else {
- Code << getStore(P, V->getType(), VS, Alignment) + ';';
+ Code << getStore(P, V->getType(), VS, Alignment) << ';';
}
Type *T = V->getType();
@@ -1198,10 +1235,10 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
break;
}
case Instruction::PtrToInt:
- Code << getAssign(iName, Type::getInt32Ty(I->getContext())) + getPtrAsStr(I->getOperand(0)) + ';';
+ Code << getAssign(iName, Type::getInt32Ty(I->getContext())) << getPtrAsStr(I->getOperand(0)) << ';';
break;
case Instruction::IntToPtr:
- Code << getAssign(iName, Type::getInt32Ty(I->getContext())) + getValueAsStr(I->getOperand(0)) + ";";
+ Code << getAssign(iName, Type::getInt32Ty(I->getContext())) << getValueAsStr(I->getOperand(0)) << ";";
break;
case Instruction::Trunc:
case Instruction::ZExt:
@@ -1217,12 +1254,12 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
case Instruction::Trunc: {
//unsigned inBits = V->getType()->getIntegerBitWidth();
unsigned outBits = I->getType()->getIntegerBitWidth();
- Code << getValueAsStr(I->getOperand(0)) + "&" + utostr(LSBMask(outBits));
+ Code << getValueAsStr(I->getOperand(0)) << "&" << utostr(LSBMask(outBits));
break;
}
case Instruction::SExt: {
std::string bits = utostr(32 - I->getOperand(0)->getType()->getIntegerBitWidth());
- Code << getValueAsStr(I->getOperand(0)) + " << " + bits + " >> " + bits;
+ Code << getValueAsStr(I->getOperand(0)) << " << " << bits << " >> " << bits;
break;
}
case Instruction::ZExt: Code << getValueAsCastStr(I->getOperand(0), ASM_UNSIGNED); break;
@@ -1247,33 +1284,33 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
std::string V = getValueAsStr(I->getOperand(0));
if (InType->isIntegerTy() && OutType->isFloatingPointTy()) {
assert(InType->getIntegerBitWidth() == 32);
- Code << "(HEAP32[tempDoublePtr>>2]=" + V + "," + "+HEAPF32[tempDoublePtr>>2]);";
+ Code << "(HEAP32[tempDoublePtr>>2]=" << V << "," << "+HEAPF32[tempDoublePtr>>2]);";
} else if (OutType->isIntegerTy() && InType->isFloatingPointTy()) {
assert(OutType->getIntegerBitWidth() == 32);
- Code << "(HEAPF32[tempDoublePtr>>2]=" + V + "," + "HEAP32[tempDoublePtr>>2]|0);";
+ Code << "(HEAPF32[tempDoublePtr>>2]=" << V << "," << "HEAP32[tempDoublePtr>>2]|0);";
} else {
- Code << V + ";";
+ Code << V << ";";
}
break;
}
case Instruction::Call: {
const CallInst *CI = cast<CallInst>(I);
- Code << handleCall(CI) + ';';
+ Code << handleCall(CI) << ';';
break;
}
case Instruction::Select: {
const SelectInst* SI = cast<SelectInst>(I);
- Code << getAssign(iName, I->getType()) + getValueAsStr(SI->getCondition()) + " ? " +
- getValueAsStr(SI->getTrueValue()) + " : " +
- getValueAsStr(SI->getFalseValue()) + ';';
+ Code << getAssign(iName, I->getType()) << getValueAsStr(SI->getCondition()) << " ? " <<
+ getValueAsStr(SI->getTrueValue()) << " : " <<
+ getValueAsStr(SI->getFalseValue()) << ';';
break;
}
case Instruction::AtomicCmpXchg: {
std::string Assign = getAssign(iName, I->getType());
const Value *P = I->getOperand(0);
- Code << getLoad(Assign, P, I->getType(), 0) + ';' +
- "if ((" + getCast(iName, I->getType()) + ") == " + getValueAsCastParenStr(I->getOperand(1)) + ") " +
- getStore(P, I->getType(), getValueAsStr(I->getOperand(2)), 0) + ";";
+ Code << getLoad(Assign, P, I->getType(), 0) << ';' <<
+ "if ((" << getCast(iName, I->getType()) << ") == " << getValueAsCastParenStr(I->getOperand(1)) << ") " <<
+ getStore(P, I->getType(), getValueAsStr(I->getOperand(2)), 0) << ";";
break;
}
case Instruction::AtomicRMW: {
@@ -1282,7 +1319,7 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
const Value *V = rmwi->getOperand(1);
std::string Assign = getAssign(iName, I->getType());
std::string VS = getValueAsStr(V);
- Code << getLoad(Assign, P, I->getType(), 0) + ';';
+ Code << getLoad(Assign, P, I->getType(), 0) << ';';
// Most bitcasts are no-ops for us. However, the exception is int to float and float to int
switch (rmwi->getOperation()) {
case AtomicRMWInst::Xchg: Code << getStore(P, I->getType(), VS, 0); break;
@@ -1307,7 +1344,7 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod
DILocation Loc(N);
unsigned Line = Loc.getLineNumber();
StringRef File = Loc.getFilename();
- Code << " //@line " + utostr(Line) + " \"" + (File.size() > 0 ? File.str() : "?") + "\"";
+ Code << " //@line " << utostr(Line) << " \"" << (File.size() > 0 ? File.str() : "?") << "\"";
}
}
@@ -1466,7 +1503,7 @@ void JSWriter::printFunctionBody(const Function *F) {
}
// Emit stack entry
- Out << " " + getAssign("sp", Type::getInt32Ty(F->getContext())) + "STACKTOP;";
+ Out << " " << getAssign("sp", Type::getInt32Ty(F->getContext())) << "STACKTOP;";
// Emit (relooped) code
char *buffer = Relooper::GetOutputBuffer();
@@ -1479,7 +1516,7 @@ void JSWriter::printFunctionBody(const Function *F) {
if (!LastCurly) LastCurly = buffer;
char *FinalReturn = strstr(LastCurly, "return ");
if (!FinalReturn) {
- Out << " return " + getCast("0", RT, ASM_NONSPECIFIC) + ";\n";
+ Out << " return " << getCast("0", RT, ASM_NONSPECIFIC) << ";\n";
}
}
}
@@ -1558,7 +1595,7 @@ void JSWriter::printModuleBody() {
}
}
Out << " function runPostSets() {\n";
- Out << " " + PostSets + "\n";
+ Out << " " << PostSets << "\n";
Out << " }\n";
PostSets = "";
Out << "// EMSCRIPTEN_END_FUNCTIONS\n\n";
@@ -1592,7 +1629,7 @@ void JSWriter::printModuleBody() {
} else {
Out << ", ";
}
- Out << "\"" + I->getName() + "\"";
+ Out << "\"" << I->getName() << "\"";
}
}
for (NameSet::iterator I = Declares.begin(), E = Declares.end();
@@ -1602,7 +1639,7 @@ void JSWriter::printModuleBody() {
} else {
Out << ", ";
}
- Out << "\"" + *I + "\"";
+ Out << "\"" << *I << "\"";
}
Out << "],";
@@ -1615,7 +1652,7 @@ void JSWriter::printModuleBody() {
} else {
Out << ", ";
}
- Out << "\"_" << I->first << "\": \"" + I->second + "\"";
+ Out << "\"_" << I->first << "\": \"" << I->second << "\"";
}
Out << "},";
@@ -1628,7 +1665,7 @@ void JSWriter::printModuleBody() {
} else {
Out << ", ";
}
- Out << "\"" + *I + "\"";
+ Out << "\"" << *I << "\"";
}
Out << "],";
@@ -1650,7 +1687,7 @@ void JSWriter::printModuleBody() {
Out << "\"tables\": {";
unsigned Num = FunctionTables.size();
for (FunctionTableMap::iterator I = FunctionTables.begin(), E = FunctionTables.end(); I != E; ++I) {
- Out << " \"" + I->first + "\": \"var FUNCTION_TABLE_" + I->first + " = [";
+ Out << " \"" << I->first << "\": \"var FUNCTION_TABLE_" << I->first << " = [";
FunctionTable &Table = I->second;
// ensure power of two
unsigned Size = 1;
@@ -1674,7 +1711,7 @@ void JSWriter::printModuleBody() {
} else {
Out << ", ";
}
- Out << "\"" + GlobalInitializers[i] + "\"";
+ Out << "\"" << GlobalInitializers[i] << "\"";
}
Out << "],";
@@ -1690,7 +1727,7 @@ void JSWriter::printModuleBody() {
} else {
Out << ", ";
}
- Out << "\"_" << I->first << "\": \"" + utostr(I->second) + "\"";
+ Out << "\"_" << I->first << "\": \"" << utostr(I->second) << "\"";
}
Out << "}";