diff options
-rw-r--r-- | clang/include/clang/Basic/Builtins.def | 1 | ||||
-rw-r--r-- | clang/include/clang/Basic/LangOptions.def | 4 | ||||
-rw-r--r-- | clang/include/clang/Basic/XRayInstr.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Driver/Options.td | 6 | ||||
-rw-r--r-- | clang/include/clang/Driver/XRayArgs.h | 1 | ||||
-rw-r--r-- | clang/include/clang/Frontend/CodeGenOptions.def | 3 | ||||
-rw-r--r-- | clang/lib/Basic/XRayInstr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 38 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 4 | ||||
-rw-r--r-- | clang/lib/Driver/XRayArgs.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 7 | ||||
-rw-r--r-- | clang/test/CodeGen/xray-always-emit-typedevent.cpp | 10 | ||||
-rw-r--r-- | clang/test/CodeGen/xray-instrumentation-bundles.cpp | 35 | ||||
-rw-r--r-- | clang/test/CodeGen/xray-typedevent.cpp | 34 |
15 files changed, 153 insertions, 11 deletions
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 4b7466277ba..189c8557356 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -1455,6 +1455,7 @@ LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG) // Builtins for XRay BUILTIN(__xray_customevent, "vcC*z", "") +BUILTIN(__xray_typedevent, "vzcC*z", "") // Win64-compatible va_list functions BUILTIN(__builtin_ms_va_start, "vc*&.", "nt") diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index c05f0dc545e..029e6516c0a 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -281,6 +281,9 @@ LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation") LANGOPT(XRayAlwaysEmitCustomEvents, 1, 0, "controls whether to always emit intrinsic calls to " "__xray_customevent(...) builtin.") +LANGOPT(XRayAlwaysEmitTypedEvents, 1, 0, + "controls whether to always emit intrinsic calls to " + "__xray_typedevent(...) builtin.") BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source") @@ -298,4 +301,3 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, #undef VALUE_LANGOPT #undef COMPATIBLE_VALUE_LANGOPT #undef BENIGN_VALUE_LANGOPT - diff --git a/clang/include/clang/Basic/XRayInstr.h b/clang/include/clang/Basic/XRayInstr.h index a573ba1eca3..6a03c7b5e26 100644 --- a/clang/include/clang/Basic/XRayInstr.h +++ b/clang/include/clang/Basic/XRayInstr.h @@ -31,13 +31,15 @@ namespace XRayInstrKind { enum XRayInstrOrdinal : XRayInstrMask { XRIO_Function, XRIO_Custom, + XRIO_Typed, XRIO_Count }; constexpr XRayInstrMask None = 0; constexpr XRayInstrMask Function = 1U << XRIO_Function; constexpr XRayInstrMask Custom = 1U << XRIO_Custom; -constexpr XRayInstrMask All = Function | Custom; +constexpr XRayInstrMask Typed = 1U << XRIO_Typed; +constexpr XRayInstrMask All = Function | Custom | Typed; } // namespace XRayInstrKind diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 09f759e9965..55e87287585 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1119,6 +1119,12 @@ def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group<f_Group>, Flags<[CC1Option]>; +def fxray_always_emit_typedevents : Flag<["-"], "fxray-always-emit-typedevents">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Determine whether to always emit __xray_typedevent(...) calls even if the function it appears in is not always instrumented.">; +def fnoxray_always_emit_typedevents : Flag<["-"], "fno-xray-always-emit-typedevents">, Group<f_Group>, + Flags<[CC1Option]>; + def fxray_link_deps : Flag<["-"], "fxray-link-deps">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Tells clang to add the link dependencies for XRay.">; diff --git a/clang/include/clang/Driver/XRayArgs.h b/clang/include/clang/Driver/XRayArgs.h index fd041d9bc58..c7ca9452917 100644 --- a/clang/include/clang/Driver/XRayArgs.h +++ b/clang/include/clang/Driver/XRayArgs.h @@ -29,6 +29,7 @@ class XRayArgs { bool XRayInstrument = false; int InstructionThreshold = 200; bool XRayAlwaysEmitCustomEvents = false; + bool XRayAlwaysEmitTypedEvents = false; bool XRayRT = true; public: diff --git a/clang/include/clang/Frontend/CodeGenOptions.def b/clang/include/clang/Frontend/CodeGenOptions.def index 8d710b0c6f9..684f99e1de3 100644 --- a/clang/include/clang/Frontend/CodeGenOptions.def +++ b/clang/include/clang/Frontend/CodeGenOptions.def @@ -96,6 +96,9 @@ CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabl ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) +///< Set when -fxray-always-emit-typedevents is enabled. +CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0) + ///< Set the minimum number of instructions in a function to determine selective ///< XRay instrumentation. VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200) diff --git a/clang/lib/Basic/XRayInstr.cpp b/clang/lib/Basic/XRayInstr.cpp index 42f9038890a..8cc36df7946 100644 --- a/clang/lib/Basic/XRayInstr.cpp +++ b/clang/lib/Basic/XRayInstr.cpp @@ -21,6 +21,7 @@ XRayInstrMask parseXRayInstrValue(StringRef Value) { .Case("all", XRayInstrKind::All) .Case("custom", XRayInstrKind::Custom) .Case("function", XRayInstrKind::Function) + .Case("typed", XRayInstrKind::Typed) .Case("none", XRayInstrKind::None) .Default(XRayInstrKind::None); return ParsedKind; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index dd245dd5590..fffc2429fb1 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3372,6 +3372,44 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall(F, {Arg0Val, Arg1})); } + case Builtin::BI__xray_typedevent: { + // TODO: There should be a way to always emit events even if the current + // function is not instrumented. Losing events in a stream can cripple + // a trace. + if (!ShouldXRayInstrumentFunction()) + return RValue::getIgnored(); + + if (!CGM.getCodeGenOpts().XRayInstrumentationBundle.has( + XRayInstrKind::Typed)) + return RValue::getIgnored(); + + if (const auto *XRayAttr = CurFuncDecl->getAttr<XRayInstrumentAttr>()) + if (XRayAttr->neverXRayInstrument() && !AlwaysEmitXRayTypedEvents()) + return RValue::getIgnored(); + + Function *F = CGM.getIntrinsic(Intrinsic::xray_typedevent); + auto FTy = F->getFunctionType(); + auto Arg0 = EmitScalarExpr(E->getArg(0)); + auto PTy0 = FTy->getParamType(0); + if (PTy0 != Arg0->getType()) + Arg0 = Builder.CreateTruncOrBitCast(Arg0, PTy0); + auto Arg1 = E->getArg(1); + auto Arg1Val = EmitScalarExpr(Arg1); + auto Arg1Ty = Arg1->getType(); + auto PTy1 = FTy->getParamType(1); + if (PTy1 != Arg1Val->getType()) { + if (Arg1Ty->isArrayType()) + Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); + else + Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); + } + auto Arg2 = EmitScalarExpr(E->getArg(2)); + auto PTy2 = FTy->getParamType(2); + if (PTy2 != Arg2->getType()) + Arg2 = Builder.CreateTruncOrBitCast(Arg2, PTy2); + return RValue::get(Builder.CreateCall(F, {Arg0, Arg1Val, Arg2})); + } + case Builtin::BI__builtin_ms_va_start: case Builtin::BI__builtin_ms_va_end: return RValue::get( diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 92564043e07..bf5312550b7 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -466,7 +466,7 @@ bool CodeGenFunction::ShouldXRayInstrumentFunction() const { } /// AlwaysEmitXRayCustomEvents - Return true if we should emit IR for calls to -/// the __xray_customevent(...) builin calls, when doing XRay instrumentation. +/// the __xray_customevent(...) builtin calls, when doing XRay instrumentation. bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const { return CGM.getCodeGenOpts().XRayInstrumentFunctions && (CGM.getCodeGenOpts().XRayAlwaysEmitCustomEvents || @@ -474,6 +474,13 @@ bool CodeGenFunction::AlwaysEmitXRayCustomEvents() const { XRayInstrKind::Custom); } +bool CodeGenFunction::AlwaysEmitXRayTypedEvents() const { + return CGM.getCodeGenOpts().XRayInstrumentFunctions && + (CGM.getCodeGenOpts().XRayAlwaysEmitTypedEvents || + CGM.getCodeGenOpts().XRayInstrumentationBundle.Mask == + XRayInstrKind::Typed); +} + llvm::Constant * CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F, llvm::Constant *Addr) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 84118a50c1d..091fdc7ab7a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1804,6 +1804,10 @@ public: /// XRay custom event handling calls. bool AlwaysEmitXRayCustomEvents() const; + /// AlwaysEmitXRayTypedEvents - Return true if clang must unconditionally emit + /// XRay typed event handling calls. + bool AlwaysEmitXRayTypedEvents() const; + /// Encode an address into a form suitable for use in a function prologue. llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F, llvm::Constant *Addr); diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp index 873693354d1..5caeffc9d6e 100644 --- a/clang/lib/Driver/XRayArgs.cpp +++ b/clang/lib/Driver/XRayArgs.cpp @@ -77,6 +77,10 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) { options::OPT_fnoxray_always_emit_customevents, false)) XRayAlwaysEmitCustomEvents = true; + if (Args.hasFlag(options::OPT_fxray_always_emit_typedevents, + options::OPT_fnoxray_always_emit_typedevents, false)) + XRayAlwaysEmitTypedEvents = true; + if (!Args.hasFlag(options::OPT_fxray_link_deps, options::OPT_fnoxray_link_deps, true)) XRayRT = false; @@ -174,6 +178,9 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args, if (XRayAlwaysEmitCustomEvents) CmdArgs.push_back("-fxray-always-emit-customevents"); + if (XRayAlwaysEmitTypedEvents) + CmdArgs.push_back("-fxray-always-emit-typedevents"); + CmdArgs.push_back(Args.MakeArgString(Twine(XRayInstructionThresholdOption) + Twine(InstructionThreshold))); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 469497c485f..9146d2a36df 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -854,6 +854,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_fxray_instrument); Opts.XRayAlwaysEmitCustomEvents = Args.hasArg(OPT_fxray_always_emit_customevents); + Opts.XRayAlwaysEmitTypedEvents = + Args.hasArg(OPT_fxray_always_emit_typedevents); Opts.XRayInstructionThreshold = getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags); @@ -2678,6 +2680,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Args.hasFlag(OPT_fxray_always_emit_customevents, OPT_fnoxray_always_emit_customevents, false); + // -fxray-always-emit-typedevents + Opts.XRayAlwaysEmitTypedEvents = + Args.hasFlag(OPT_fxray_always_emit_typedevents, + OPT_fnoxray_always_emit_customevents, false); + // -fxray-{always,never}-instrument= filenames. Opts.XRayAlwaysInstrumentFiles = Args.getAllArgValues(OPT_fxray_always_instrument); diff --git a/clang/test/CodeGen/xray-always-emit-typedevent.cpp b/clang/test/CodeGen/xray-always-emit-typedevent.cpp new file mode 100644 index 00000000000..50593dd2032 --- /dev/null +++ b/clang/test/CodeGen/xray-always-emit-typedevent.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fxray-instrument -fxray-always-emit-typedevents -x c++ \ +// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck %s + +// CHECK-LABEL: @_Z15neverInstrumentv +[[clang::xray_never_instrument]] void neverInstrument() { + static constexpr char kPhase[] = "never"; + __xray_typedevent(1, kPhase, 5); + // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 5) +} diff --git a/clang/test/CodeGen/xray-instrumentation-bundles.cpp b/clang/test/CodeGen/xray-instrumentation-bundles.cpp index 3e751834475..79286c2c8ae 100644 --- a/clang/test/CodeGen/xray-instrumentation-bundles.cpp +++ b/clang/test/CodeGen/xray-instrumentation-bundles.cpp @@ -1,30 +1,49 @@ // RUN: %clang_cc1 -fxray-instrument -fxray-instrumentation-bundle=none -x c++ \ // RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,NOCUSTOM %s -// RUN: %clang_cc1 -fxray-instrument \ -// RUN: -fxray-instrumentation-bundle=function -x c++ \ +// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,NOCUSTOM,NOTYPED %s +// RUN: %clang_cc1 -fxray-instrument -fxray-instrumentation-bundle=function -x c++ \ // RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,NOCUSTOM %s +// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,NOCUSTOM,NOTYPED %s // RUN: %clang_cc1 -fxray-instrument \ // RUN: -fxray-instrumentation-bundle=custom -x c++ \ // RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,CUSTOM %s +// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,CUSTOM,NOTYPED %s +// RUN: %clang_cc1 -fxray-instrument \ +// RUN: -fxray-instrumentation-bundle=typed -x c++ \ +// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,NOCUSTOM,TYPED %s +// RUN: %clang_cc1 -fxray-instrument \ +// RUN: -fxray-instrumentation-bundle=custom,typed -x c++ \ +// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes CHECK,NOFUNCTION,CUSTOM,TYPED %s // RUN: %clang_cc1 -fxray-instrument \ // RUN: -fxray-instrumentation-bundle=function,custom -x c++ \ // RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM %s +// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM,NOTYPED %s +// RUN: %clang_cc1 -fxray-instrument \ +// RUN: -fxray-instrumentation-bundle=function,typed -x c++ \ +// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,NOCUSTOM,TYPED %s +// RUN: %clang_cc1 -fxray-instrument \ +// RUN: -fxray-instrumentation-bundle=function,custom,typed -x c++ \ +// RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM,TYPED %s // RUN: %clang_cc1 -fxray-instrument \ // RUN: -fxray-instrumentation-bundle=function \ -// RUN: -fxray-instrumentation-bundle=custom -x c++ \ +// RUN: -fxray-instrumentation-bundle=custom \ +// RUN: -fxray-instrumentation-bundle=typed -x c++ \ // RUN: -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM %s +// RUN: | FileCheck --check-prefixes CHECK,FUNCTION,CUSTOM,TYPED %s // CHECK: define void @_Z16alwaysInstrumentv() #[[ALWAYSATTR:[0-9]+]] { [[clang::xray_always_instrument]] void alwaysInstrument() { static constexpr char kPhase[] = "always"; __xray_customevent(kPhase, 6); + __xray_typedevent(1, kPhase, 6); // CUSTOM: call void @llvm.xray.customevent(i8*{{.*}}, i32 6) // NOCUSTOM-NOT: call void @llvm.xray.customevent(i8*{{.*}}, i32 6) + // TYPED: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 6) + // NOTYPED-NOT: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 6) } // FUNCTION: attributes #[[ALWAYSATTR]] = {{.*}} "function-instrument"="xray-always" {{.*}} diff --git a/clang/test/CodeGen/xray-typedevent.cpp b/clang/test/CodeGen/xray-typedevent.cpp new file mode 100644 index 00000000000..e804b09dc2c --- /dev/null +++ b/clang/test/CodeGen/xray-typedevent.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fxray-instrument -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: @_Z16alwaysInstrumentv +[[clang::xray_always_instrument]] void alwaysInstrument() { + // Event types would normally come from calling __xray_register_event_type + // from compiler-rt + auto EventType = 1; + static constexpr char kPhase[] = "instrument"; + __xray_typedevent(EventType, kPhase, 10); + // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 10) +} + +// CHECK-LABEL: @_Z15neverInstrumentv +[[clang::xray_never_instrument]] void neverInstrument() { + auto EventType = 2; + static constexpr char kPhase[] = "never"; + __xray_typedevent(EventType, kPhase, 5); + // CHECK-NOT: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 5) +} + +// CHECK-LABEL: @_Z21conditionalInstrumenti +[[clang::xray_always_instrument]] void conditionalInstrument(int v) { + auto TrueEventType = 3; + auto UntrueEventType = 4; + static constexpr char kTrue[] = "true"; + static constexpr char kUntrue[] = "untrue"; + if (v % 2) + __xray_typedevent(TrueEventType, kTrue, 4); + else + __xray_typedevent(UntrueEventType, kUntrue, 6); + + // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 4) + // CHECK: call void @llvm.xray.typedevent(i16 {{.*}}, i8*{{.*}}, i32 6) +} |