diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -5416,6 +5416,7 @@ Function &F; MemorySanitizer &MS; MemorySanitizerVisitor &MSV; + bool IsSoftFloatABI; Value *VAArgTLSCopy = nullptr; Value *VAArgTLSOriginCopy = nullptr; Value *VAArgOverflowSize = nullptr; @@ -5434,9 +5435,10 @@ VarArgSystemZHelper(Function &F, MemorySanitizer &MS, MemorySanitizerVisitor &MSV) - : F(F), MS(MS), MSV(MSV) {} + : F(F), MS(MS), MSV(MSV), + IsSoftFloatABI(F.getFnAttribute("use-soft-float").getValueAsBool()) {} - ArgKind classifyArgument(Type *T, bool IsSoftFloatABI) { + ArgKind classifyArgument(Type *T) { // T is a SystemZABIInfo::classifyArgumentType() output, and there are // only a few possibilities of what it can be. In particular, enums, single // element structs and large types have already been taken care of. @@ -5474,9 +5476,6 @@ } void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override { - bool IsSoftFloatABI = CB.getCalledFunction() - ->getFnAttribute("use-soft-float") - .getValueAsBool(); unsigned GpOffset = SystemZGpOffset; unsigned FpOffset = SystemZFpOffset; unsigned VrIndex = 0; @@ -5487,7 +5486,7 @@ // SystemZABIInfo does not produce ByVal parameters. assert(!CB.paramHasAttr(ArgNo, Attribute::ByVal)); Type *T = A->getType(); - ArgKind AK = classifyArgument(T, IsSoftFloatABI); + ArgKind AK = classifyArgument(T); if (AK == ArgKind::Indirect) { T = PointerType::get(T, 0); AK = ArgKind::GeneralPurpose; diff --git a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll --- a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll @@ -31,7 +31,7 @@ ret i64 %1 } -attributes #1 = { sanitize_memory } +attributes #1 = { sanitize_memory "target-features"="+soft-float" "use-soft-float"="true" } ; In kernel the floating point values are passed in GPRs: ; - r2@16 == i64 1 - skipped, because it's fixed diff --git a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll --- a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg.ll @@ -197,3 +197,16 @@ ; CHECK: declare void @__msan_maybe_store_origin_4(i32 zeroext, ptr, i32 zeroext) ; CHECK: declare void @__msan_maybe_warning_8(i64 zeroext, i32 zeroext) ; CHECK: declare void @__msan_maybe_store_origin_8(i64 zeroext, ptr, i32 zeroext) + +; Test vararg function pointers. +; +; void (*ptr)(int, ...); +; void call_ptr(void) { ptr(0); } + +@ptr = dso_local global ptr null, align 8 + +define dso_local void @call_ptr() { + %1 = load ptr, ptr @ptr, align 8 + call void (i32, ...) %1(i32 noundef signext 0) + ret void +}