diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -102,6 +102,7 @@ bool *Fast) const override; bool isIntDivCheap(EVT VT, AttributeList Attr) const override; bool isVectorLoadExtDesirable(SDValue ExtVal) const override; + bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override; bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -770,6 +770,13 @@ (ExtT == MVT::v2i64 && MemT == MVT::v2i32); } +bool WebAssemblyTargetLowering::isOffsetFoldingLegal( + const GlobalAddressSDNode *GA) const { + // Wasm doesn't support function addresses with offsets + const GlobalValue *GV = GA->getGlobal(); + return isa(GV) ? false : TargetLowering::isOffsetFoldingLegal(GA); +} + EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL, LLVMContext &C, EVT VT) const { diff --git a/llvm/test/CodeGen/WebAssembly/function-pointer-offset.ll b/llvm/test/CodeGen/WebAssembly/function-pointer-offset.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/function-pointer-offset.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s -verify-machineinstrs | FileCheck %s + +; Wasm does not currently support function addresses with offsets, so we +; shouldn't try to create a folded SDNode like (function + offset). This is a +; regression test for the folding bug and this should not crash in MCInstLower. + +target triple = "wasm32-unknown-unknown" + +declare hidden void @ham(i8*) + +define void @bar(i8* %ptr) { +bb1: + br i1 undef, label %bb3, label %bb2 + +bb2: + ; While lowering this switch, isel creates (@ham + 1) expression as a course + ; of range optimization for switch, and tries to fold the expression, but + ; wasm does not support with function addresses with offsets. This folding + ; should be disabled. + ; CHECK: i32.const ham + ; CHECK-NEXT: i32.const 1 + ; CHECK-NEXT: i32.add + switch i32 ptrtoint (void (i8*)* @ham to i32), label %bb4 [ + i32 -1, label %bb3 + i32 0, label %bb3 + ] + +bb3: + unreachable + +bb4: + %tmp = load i8, i8* %ptr + unreachable +}