LLVM's stripPointerCasts can now look through a call/invoke (possibly with side effects) if it has a param with the 'returned' attribute
diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h
index bdda7dd..23159b9 100644
--- a/lib/Target/JSBackend/CallHandlers.h
+++ b/lib/Target/JSBackend/CallHandlers.h
@@ -24,7 +24,7 @@
// 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<const Function>(CV->stripPointerCasts())) {
+ if (const Function *F = dyn_cast<const Function>(stripPointerCastsWithoutSideEffects(CV))) {
CV = F;
}
return CV;
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp
index 8093570..cb0a596 100644
--- a/lib/Target/JSBackend/JSBackend.cpp
+++ b/lib/Target/JSBackend/JSBackend.cpp
@@ -299,6 +299,19 @@
raw_pwrite_stream& nl(raw_pwrite_stream &Out, int delta = 0);
private:
+
+ // LLVM changed stripPointerCasts to use the "returned" attribute on
+ // calls and invokes, i.e., stripping pointer casts of a call to
+ // define internal i8* @strupr(i8* returned %str) #2 {
+ // will return the pointer, and ignore the call which has side
+ // effects. We sometimes do care about the side effects.
+ const Value* stripPointerCastsWithoutSideEffects(const Value* V) {
+ if (isa<CallInst>(V) || isa<InvokeInst>(V)) {
+ return V; // in theory we could check if there actually are side effects
+ }
+ return V->stripPointerCasts();
+ }
+
void printCommaSeparated(const HeapData v);
// parsing of constants has two phases: calculate, and then emit
@@ -1679,7 +1692,7 @@
std::string JSWriter::getValueAsStr(const Value* V, AsmCast sign) {
// Skip past no-op bitcasts and zero-index geps.
- V = V->stripPointerCasts();
+ V = stripPointerCastsWithoutSideEffects(V);
if (const Constant *CV = dyn_cast<Constant>(V)) {
return getConstant(CV, sign);
@@ -1690,7 +1703,7 @@
std::string JSWriter::getValueAsCastStr(const Value* V, AsmCast sign) {
// Skip past no-op bitcasts and zero-index geps.
- V = V->stripPointerCasts();
+ V = stripPointerCastsWithoutSideEffects(V);
if (isa<ConstantInt>(V) || isa<ConstantFP>(V)) {
return getConstant(cast<Constant>(V), sign);
@@ -1701,7 +1714,7 @@
std::string JSWriter::getValueAsParenStr(const Value* V) {
// Skip past no-op bitcasts and zero-index geps.
- V = V->stripPointerCasts();
+ V = stripPointerCastsWithoutSideEffects(V);
if (const Constant *CV = dyn_cast<Constant>(V)) {
return getConstant(CV);
@@ -1712,7 +1725,7 @@
std::string JSWriter::getValueAsCastParenStr(const Value* V, AsmCast sign) {
// Skip past no-op bitcasts and zero-index geps.
- V = V->stripPointerCasts();
+ V = stripPointerCastsWithoutSideEffects(V);
if (isa<ConstantInt>(V) || isa<ConstantFP>(V) || isa<UndefValue>(V)) {
return getConstant(cast<Constant>(V), sign);
@@ -2362,7 +2375,7 @@
// and all-zero-index geps that LLVM needs to satisfy its type system, we
// call stripPointerCasts() on all values before translating them. This
// includes bitcasts whose only use is lifetime marker intrinsics.
- assert(I == I->stripPointerCasts());
+ assert(I == stripPointerCastsWithoutSideEffects(I));
Type *T = I->getType();
if (T->isIntegerTy() && ((!OnlyWebAssembly && T->getIntegerBitWidth() > 32) ||
@@ -2961,7 +2974,7 @@
for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
II != E; ++II) {
auto I = &*II;
- if (I->stripPointerCasts() == I) {
+ if (stripPointerCastsWithoutSideEffects(I) == I) {
CurrInstruction = I;
generateExpression(I, CodeStream);
}