diff --git a/clang/test/CodeGen/fat-lto-objects-cfi.cpp b/clang/test/CodeGen/fat-lto-objects-cfi.cpp new file mode 100644 index 00000000000000..628951847053ac --- /dev/null +++ b/clang/test/CodeGen/fat-lto-objects-cfi.cpp @@ -0,0 +1,46 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-unknown-fuchsia -O2 -flto -ffat-lto-objects \ +// RUN: -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -fvisibility=hidden -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// CHECK: llvm.embedded.object +// CHECK-SAME: section ".llvm.lto" + +// CHECK-LABEL: define hidden void @foo +// CHECK: entry: +// CHECK-NEXT: %cmp14.not = icmp eq i64 %len, 0 +// CHECK-NEXT: br i1 %cmp14.not, label %for.end7, label %for.cond1.preheader.preheader +// CHECK: for.cond1.preheader.preheader: ; preds = %entry +// CHECK-NEXT: %arrayidx.1 = getelementptr inbounds nuw i8, ptr %ptr, i64 4 +// CHECK-NEXT: br label %for.cond1.preheader + +// CHECK-NOT: @llvm.type.test + +// The code below is a reduced case from https://github.com/llvm/llvm-project/issues/112053 +#define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs))) +typedef void func(void* arg, const char* fmt, ...) __PRINTFLIKE(2, 3); +typedef __SIZE_TYPE__ size_t; +typedef unsigned long uintptr_t; + +extern "C" +void foo(const void* ptr, size_t len, long disp_addr, + func* printf_func, void* printf_arg) { + uintptr_t address = (uintptr_t)ptr; + size_t count; + + for (count = 0; count < len; count += 16) { + union { + unsigned int buf[4]; + unsigned char cbuf[16]; + } u; + size_t s = 10; + size_t i; + + for (i = 0; i < s / 4; i++) { + u.buf[i] = ((const unsigned int*)address)[i]; + printf_func(printf_arg, "%08x ", static_cast(u.buf[i])); + } + } +} + diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 6478667e22b851..0585e83e59a9ab 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1630,6 +1630,13 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO, MPM.addPass(buildLTOPreLinkDefaultPipeline(Level)); MPM.addPass(EmbedBitcodePass(ThinLTO, EmitSummary)); + // If we're doing FatLTO w/ CFI enabled, we don't want the type tests in the + // object code, only in the bitcode section, so drop it before we run + // module optimization and generate machine code. If llvm.type.test() isn't in + // the IR, this won't do anything. + MPM.addPass( + LowerTypeTestsPass(nullptr, nullptr, lowertypetests::DropTestKind::All)); + // Use the ThinLTO post-link pipeline with sample profiling if (ThinLTO && PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) MPM.addPass(buildThinLTODefaultPipeline(Level, /*ImportSummary=*/nullptr));