melver updated this revision to Diff 346577. melver added a comment. Herald added a subscriber: steven_wu.
Rest of long-tail of IR changes related to introducing a new attributes... Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D102772/new/ https://reviews.llvm.org/D102772 Files: clang/docs/SanitizerCoverage.rst clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/CodeGen/sanitize-coverage.c llvm/bindings/go/llvm/ir_test.go llvm/docs/BitCodeFormat.rst llvm/docs/LangRef.rst llvm/include/llvm/AsmParser/LLToken.h llvm/include/llvm/Bitcode/LLVMBitCodes.h llvm/include/llvm/IR/Attributes.td llvm/lib/AsmParser/LLLexer.cpp llvm/lib/AsmParser/LLParser.cpp llvm/lib/Bitcode/Reader/BitcodeReader.cpp llvm/lib/Bitcode/Writer/BitcodeWriter.cpp llvm/lib/IR/Attributes.cpp llvm/lib/IR/Verifier.cpp llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp llvm/lib/Transforms/Utils/CodeExtractor.cpp llvm/test/Bitcode/attributes.ll llvm/test/Bitcode/compatibility.ll llvm/utils/emacs/llvm-mode.el llvm/utils/llvm.grm llvm/utils/vim/syntax/llvm.vim llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml
Index: llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml =================================================================== --- llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml +++ llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml @@ -237,6 +237,7 @@ \\bnosync\\b|\ \\bnoundef\\b|\ \\bnounwind\\b|\ + \\bno_sanitize_coverage\\b|\ \\bnull_pointer_is_valid\\b|\ \\boptforfuzzing\\b|\ \\boptnone\\b|\ Index: llvm/utils/vim/syntax/llvm.vim =================================================================== --- llvm/utils/vim/syntax/llvm.vim +++ llvm/utils/vim/syntax/llvm.vim @@ -138,6 +138,7 @@ \ nosync \ noundef \ nounwind + \ no_sanitize_coverage \ null_pointer_is_valid \ optforfuzzing \ optnone Index: llvm/utils/llvm.grm =================================================================== --- llvm/utils/llvm.grm +++ llvm/utils/llvm.grm @@ -176,6 +176,7 @@ | sanitize_thread | sanitize_memory | mustprogress + | no_sanitize_coverage ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; Index: llvm/utils/emacs/llvm-mode.el =================================================================== --- llvm/utils/emacs/llvm-mode.el +++ llvm/utils/emacs/llvm-mode.el @@ -25,7 +25,7 @@ '("alwaysinline" "argmemonly" "allocsize" "builtin" "cold" "convergent" "dereferenceable" "dereferenceable_or_null" "hot" "inaccessiblememonly" "inaccessiblemem_or_argmemonly" "inalloca" "inlinehint" "jumptable" "minsize" "mustprogress" "naked" "nobuiltin" "nonnull" "nocallback" "nocf_check" "noduplicate" "nofree" "noimplicitfloat" "noinline" "nomerge" "nonlazybind" "noprofile" "noredzone" "noreturn" - "norecurse" "nosync" "noundef" "nounwind" "null_pointer_is_valid" "optforfuzzing" "optnone" "optsize" "preallocated" "readnone" "readonly" "returned" "returns_twice" + "norecurse" "nosync" "noundef" "nounwind" "no_sanitize_coverage" "null_pointer_is_valid" "optforfuzzing" "optnone" "optsize" "preallocated" "readnone" "readonly" "returned" "returns_twice" "shadowcallstack" "speculatable" "speculative_load_hardening" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress" "sanitize_memtag" "sanitize_thread" "sanitize_memory" "strictfp" "swifterror" "uwtable" "vscale_range" "willreturn" "writeonly" "immarg") 'symbols) . font-lock-constant-face) ;; Variables Index: llvm/test/Bitcode/compatibility.ll =================================================================== --- llvm/test/Bitcode/compatibility.ll +++ llvm/test/Bitcode/compatibility.ll @@ -1510,7 +1510,7 @@ ; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2 x i8> <i8 3, i8 2> call void @f.nobuiltin() builtin - ; CHECK: call void @f.nobuiltin() #44 + ; CHECK: call void @f.nobuiltin() #45 call fastcc noalias i32* @f.noalias() noinline ; CHECK: call fastcc noalias i32* @f.noalias() #12 @@ -1904,6 +1904,9 @@ ret void } +declare void @f.no_sanitize_coverage() no_sanitize_coverage +; CHECK: declare void @f.no_sanitize_coverage() #44 + ; immarg attribute declare void @llvm.test.immarg.intrinsic(i32 immarg) ; CHECK: declare void @llvm.test.immarg.intrinsic(i32 immarg) @@ -1961,7 +1964,8 @@ ; CHECK: attributes #41 = { writeonly } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { strictfp } -; CHECK: attributes #44 = { builtin } +; CHECK: attributes #44 = { no_sanitize_coverage } +; CHECK: attributes #45 = { builtin } ;; Metadata Index: llvm/test/Bitcode/attributes.ll =================================================================== --- llvm/test/Bitcode/attributes.ll +++ llvm/test/Bitcode/attributes.ll @@ -453,6 +453,12 @@ ret void; } +; CHECK: define void @f77() #48 +define void @f77() no_sanitize_coverage +{ + ret void; +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -501,4 +507,5 @@ ; CHECK: attributes #45 = { vscale_range(8,8) } ; CHECK: attributes #46 = { vscale_range(1,8) } ; CHECK: attributes #47 = { vscale_range(1,0) } +; CHECK: attributes #48 = { no_sanitize_coverage } ; CHECK: attributes #[[NOBUILTIN]] = { nobuiltin } Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -954,6 +954,7 @@ case Attribute::NonLazyBind: case Attribute::NoRedZone: case Attribute::NoUnwind: + case Attribute::NoSanitizeCoverage: case Attribute::NullPointerIsValid: case Attribute::OptForFuzzing: case Attribute::OptimizeNone: Index: llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -621,6 +621,8 @@ return; if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) return; + if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) + return; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); SmallVector<Instruction *, 8> IndirCalls; Index: llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -53,6 +53,7 @@ .Case("nocf_check", Attribute::NoCfCheck) .Case("norecurse", Attribute::NoRecurse) .Case("nounwind", Attribute::NoUnwind) + .Case("no_sanitize_coverage", Attribute::NoSanitizeCoverage) .Case("optforfuzzing", Attribute::OptForFuzzing) .Case("optnone", Attribute::OptimizeNone) .Case("optsize", Attribute::OptimizeForSize) Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -1661,6 +1661,7 @@ case Attribute::NoCfCheck: case Attribute::NoUnwind: case Attribute::NoInline: + case Attribute::NoSanitizeCoverage: case Attribute::AlwaysInline: case Attribute::OptimizeForSize: case Attribute::StackProtect: Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -442,6 +442,8 @@ return "noprofile"; if (hasAttribute(Attribute::NoUnwind)) return "nounwind"; + if (hasAttribute(Attribute::NoSanitizeCoverage)) + return "no_sanitize_coverage"; if (hasAttribute(Attribute::OptForFuzzing)) return "optforfuzzing"; if (hasAttribute(Attribute::OptimizeNone)) Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -686,6 +686,8 @@ return bitc::ATTR_KIND_NO_PROFILE; case Attribute::NoUnwind: return bitc::ATTR_KIND_NO_UNWIND; + case Attribute::NoSanitizeCoverage: + return bitc::ATTR_KIND_NO_SANITIZE_COVERAGE; case Attribute::NullPointerIsValid: return bitc::ATTR_KIND_NULL_POINTER_IS_VALID; case Attribute::OptForFuzzing: Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1474,6 +1474,8 @@ return Attribute::NoCfCheck; case bitc::ATTR_KIND_NO_UNWIND: return Attribute::NoUnwind; + case bitc::ATTR_KIND_NO_SANITIZE_COVERAGE: + return Attribute::NoSanitizeCoverage; case bitc::ATTR_KIND_NULL_POINTER_IS_VALID: return Attribute::NullPointerIsValid; case bitc::ATTR_KIND_OPT_FOR_FUZZING: Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1397,6 +1397,9 @@ case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break; case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; + case lltok::kw_no_sanitize_coverage: + B.addAttribute(Attribute::NoSanitizeCoverage); + break; case lltok::kw_null_pointer_is_valid: B.addAttribute(Attribute::NullPointerIsValid); break; case lltok::kw_optforfuzzing: @@ -1824,6 +1827,7 @@ case lltok::kw_noreturn: case lltok::kw_nocf_check: case lltok::kw_nounwind: + case lltok::kw_no_sanitize_coverage: case lltok::kw_optforfuzzing: case lltok::kw_optnone: case lltok::kw_optsize: @@ -1935,6 +1939,7 @@ case lltok::kw_noreturn: case lltok::kw_nocf_check: case lltok::kw_nounwind: + case lltok::kw_no_sanitize_coverage: case lltok::kw_optforfuzzing: case lltok::kw_optnone: case lltok::kw_optsize: Index: llvm/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/lib/AsmParser/LLLexer.cpp +++ llvm/lib/AsmParser/LLLexer.cpp @@ -671,6 +671,7 @@ KEYWORD(nocf_check); KEYWORD(noundef); KEYWORD(nounwind); + KEYWORD(no_sanitize_coverage); KEYWORD(null_pointer_is_valid); KEYWORD(optforfuzzing); KEYWORD(optnone); Index: llvm/include/llvm/IR/Attributes.td =================================================================== --- llvm/include/llvm/IR/Attributes.td +++ llvm/include/llvm/IR/Attributes.td @@ -154,6 +154,9 @@ /// Function doesn't unwind stack. def NoUnwind : EnumAttr<"nounwind">; +/// No SanitizeCoverage instrumentation. +def NoSanitizeCoverage : EnumAttr<"no_sanitize_coverage">; + /// Null pointer in address space zero is valid. def NullPointerIsValid : EnumAttr<"null_pointer_is_valid">; Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -666,6 +666,7 @@ ATTR_KIND_NO_PROFILE = 73, ATTR_KIND_VSCALE_RANGE = 74, ATTR_KIND_SWIFT_ASYNC = 75, + ATTR_KIND_NO_SANITIZE_COVERAGE = 76, }; enum ComdatSelectionKindCodes { Index: llvm/include/llvm/AsmParser/LLToken.h =================================================================== --- llvm/include/llvm/AsmParser/LLToken.h +++ llvm/include/llvm/AsmParser/LLToken.h @@ -217,6 +217,7 @@ kw_nosync, kw_nocf_check, kw_nounwind, + kw_no_sanitize_coverage, kw_null_pointer_is_valid, kw_optforfuzzing, kw_optnone, Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -1691,6 +1691,9 @@ trap or generate asynchronous exceptions. Exception handling schemes that are recognized by LLVM to handle asynchronous exceptions, such as SEH, will still provide their implementation defined semantics. +``no_sanitize_coverage`` + This attribute indicates that SanitizerCoverage instrumentation is disabled + for this function. ``null_pointer_is_valid`` If ``null_pointer_is_valid`` is set, then the ``null`` address in address-space 0 is considered to be a valid address for memory loads and Index: llvm/docs/BitCodeFormat.rst =================================================================== --- llvm/docs/BitCodeFormat.rst +++ llvm/docs/BitCodeFormat.rst @@ -1073,6 +1073,8 @@ * code 69: ``byref`` * code 70: ``mustprogress`` * code 74: ``vscale_range(<Min>[, <Max>])`` +* code 75: ``swiftasync`` +* code 76: ``no_sanitize_coverage`` .. note:: The ``allocsize`` attribute has a special encoding for its arguments. Its two Index: llvm/bindings/go/llvm/ir_test.go =================================================================== --- llvm/bindings/go/llvm/ir_test.go +++ llvm/bindings/go/llvm/ir_test.go @@ -69,6 +69,7 @@ "noredzone", "noreturn", "nounwind", + "no_sanitize_coverage", "optnone", "optsize", "readnone", Index: clang/test/CodeGen/sanitize-coverage.c =================================================================== --- clang/test/CodeGen/sanitize-coverage.c +++ clang/test/CodeGen/sanitize-coverage.c @@ -19,4 +19,71 @@ if (n) x[n] = 42; } + +static inline __attribute__((__always_inline__)) void always_inlined_fn(int n) { + if (n) + x[n] = 42; +} +// CHECK-LABEL: define dso_local void @test_always_inline( +void test_always_inline(int n) { + // CHECK-DAG: call void @__sanitizer_cov_trace_pc + // CHECK-DAG: call void @__sanitizer_cov_trace_const_cmp + always_inlined_fn(n); +} + +// CHECK-LABEL: define dso_local void @test_no_sanitize_coverage( +__attribute__((no_sanitize("coverage"))) void test_no_sanitize_coverage(int n) { + // CHECK-NOT: call void @__sanitizer_cov_trace_pc + // CHECK-NOT: call void @__sanitizer_cov_trace_const_cmp + // ASAN-DAG: call void @__asan_report_store + // MSAN-DAG: call void @__msan_warning + // BOUNDS-DAG: call void @__ubsan_handle_out_of_bounds + // TSAN-DAG: call void @__tsan_func_entry + // UBSAN-DAG: call void @__ubsan_handle + if (n) + x[n] = 42; +} + + +// CHECK-LABEL: define dso_local void @test_no_sanitize_combined( +__attribute__((no_sanitize("address", "memory", "thread", "bounds", "undefined", "coverage"))) +void test_no_sanitize_combined(int n) { + // CHECK-NOT: call void @__sanitizer_cov_trace_pc + // CHECK-NOT: call void @__sanitizer_cov_trace_const_cmp + // ASAN-NOT: call void @__asan_report_store + // MSAN-NOT: call void @__msan_warning + // BOUNDS-NOT: call void @__ubsan_handle_out_of_bounds + // TSAN-NOT: call void @__tsan_func_entry + // UBSAN-NOT: call void @__ubsan_handle + if (n) + x[n] = 42; +} + +// CHECK-LABEL: define dso_local void @test_no_sanitize_separate( +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) +__attribute__((no_sanitize("thread"))) +__attribute__((no_sanitize("bounds"))) +__attribute__((no_sanitize("undefined"))) +__attribute__((no_sanitize("coverage"))) +void test_no_sanitize_separate(int n) { + // CHECK-NOT: call void @__sanitizer_cov_trace_pc + // CHECK-NOT: call void @__sanitizer_cov_trace_const_cmp + // ASAN-NOT: call void @__asan_report_store + // MSAN-NOT: call void @__msan_warning + // BOUNDS-NOT: call void @__ubsan_handle_out_of_bounds + // TSAN-NOT: call void @__tsan_func_entry + // UBSAN-NOT: call void @__ubsan_handle + if (n) + x[n] = 42; +} + +// CHECK-LABEL: define dso_local void @test_no_sanitize_always_inline( +__attribute__((no_sanitize("coverage"))) +void test_no_sanitize_always_inline(int n) { + // CHECK-NOT: call void @__sanitizer_cov_trace_pc + // CHECK-NOT: call void @__sanitizer_cov_trace_const_cmp + always_inlined_fn(n); +} + // CHECK-LABEL: declare void Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -7274,7 +7274,8 @@ return; if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == - SanitizerMask()) + SanitizerMask() && + SanitizerName != "coverage") S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; else if (isGlobalVar(D) && SanitizerName != "address") S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -734,8 +734,10 @@ } while (0); if (D) { - // Apply the no_sanitize* attributes to SanOpts. + bool NoSanitizeCoverage = false; + for (auto Attr : D->specific_attrs<NoSanitizeAttr>()) { + // Apply the no_sanitize* attributes to SanOpts. SanitizerMask mask = Attr->getMask(); SanOpts.Mask &= ~mask; if (mask & SanitizerKind::Address) @@ -746,7 +748,18 @@ SanOpts.set(SanitizerKind::KernelHWAddress, false); if (mask & SanitizerKind::KernelHWAddress) SanOpts.set(SanitizerKind::HWAddress, false); + + // SanitizeCoverage is not handled by SanOpts. + if (Attr->hasCoverage()) + NoSanitizeCoverage = true; } + + bool HaveSanitizeCoverage = + CGM.getCodeGenOpts().SanitizeCoverageType || + CGM.getCodeGenOpts().SanitizeCoverageIndirectCalls || + CGM.getCodeGenOpts().SanitizeCoverageTraceCmp; + if (NoSanitizeCoverage && HaveSanitizeCoverage) + Fn->addFnAttr(llvm::Attribute::NoSanitizeCoverage); } // Apply sanitizer attributes to the function. Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -2564,12 +2564,17 @@ let Content = [{ Use the ``no_sanitize`` attribute on a function or a global variable declaration to specify that a particular instrumentation or set of -instrumentations should not be applied. The attribute takes a list of -string literals, which have the same meaning as values accepted by the -``-fno-sanitize=`` flag. For example, -``__attribute__((no_sanitize("address", "thread")))`` specifies that -AddressSanitizer and ThreadSanitizer should not be applied to the -function or variable. +instrumentations should not be applied. + +The attribute takes a list of string literals with the following accepted +values: +* all values accepted by ``-fno-sanitize=``; +* ``coverage``, to disable SanitizerCoverage instrumentation. + +For example, ``__attribute__((no_sanitize("address", "thread")))`` specifies +that AddressSanitizer and ThreadSanitizer should not be applied to the function +or variable. Using ``__attribute__((no_sanitize("coverage")))`` specifies that +SanitizerCoverage should not be applied to the function. See :ref:`Controlling Code Generation <controlling-code-generation>` for a full list of supported sanitizer flags. Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2897,6 +2897,10 @@ } return Mask; } + + bool hasCoverage() const { + return llvm::is_contained(sanitizers(), "coverage"); + } }]; } Index: clang/docs/SanitizerCoverage.rst =================================================================== --- clang/docs/SanitizerCoverage.rst +++ clang/docs/SanitizerCoverage.rst @@ -312,11 +312,17 @@ // for every non-constant array index. void __sanitizer_cov_trace_gep(uintptr_t Idx); -Partially disabling instrumentation -=================================== +Disabling instrumentation with ``__attribute__((no_sanitize("coverage")))`` +=========================================================================== + +It is possible to disable coverage instrumentation for select functions via the +function attribute ``__attribute__((no_sanitize("coverage")))``. + +Disabling instrumentation without source modification +===================================================== It is sometimes useful to tell SanitizerCoverage to instrument only a subset of the -functions in your target. +functions in your target without modifying source files. With ``-fsanitize-coverage-allowlist=allowlist.txt`` and ``-fsanitize-coverage-blocklist=blocklist.txt``, you can specify such a subset through the combination of an allowlist and a blocklist.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits