diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 4bdf06aaaf9..529540ea4ed 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -84,7 +84,10 @@ class WebAssemblyFastISel final : public FastISel { return Base.FI; } - void setOffset(int64_t Offset_) { Offset = Offset_; } + void setOffset(int64_t Offset_) { + assert(Offset_ >= 0 && "Offsets must be non-negative"); + Offset = Offset_; + } int64_t getOffset() const { return Offset; } void setGlobalValue(const GlobalValue *G) { GV = G; } const GlobalValue *getGlobalValue() const { return GV; } @@ -236,6 +239,9 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { case Instruction::GetElementPtr: { Address SavedAddr = Addr; uint64_t TmpOffset = Addr.getOffset(); + // Non-inbounds geps can wrap; wasm's offsets can't. + if (!cast<GEPOperator>(U)->isInBounds()) + goto unsupported_gep; // Iterate through the GEP folding the constants into offsets where // we can. for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U); @@ -272,10 +278,13 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { } } } - // Try to grab the base operand now. - Addr.setOffset(TmpOffset); - if (computeAddress(U->getOperand(0), Addr)) - return true; + // Don't fold in negative offsets. + if (int64_t(TmpOffset) >= 0) { + // Try to grab the base operand now. + Addr.setOffset(TmpOffset); + if (computeAddress(U->getOperand(0), Addr)) + return true; + } // We failed, restore everything and try the other options. Addr = SavedAddr; unsupported_gep: @@ -301,8 +310,11 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { std::swap(LHS, RHS); if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) { - Addr.setOffset(Addr.getOffset() + CI->getSExtValue()); - return computeAddress(LHS, Addr); + uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue(); + if (int64_t(TmpOffset) >= 0) { + Addr.setOffset(TmpOffset); + return computeAddress(LHS, Addr); + } } Address Backup = Addr; @@ -318,8 +330,11 @@ bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { const Value *RHS = U->getOperand(1); if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) { - Addr.setOffset(Addr.getOffset() - CI->getSExtValue()); - return computeAddress(LHS, Addr); + int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue(); + if (TmpOffset >= 0) { + Addr.setOffset(TmpOffset); + return computeAddress(LHS, Addr); + } } break; } |