dberris created this revision. Herald added a subscriber: mehdi_amini. We define the `__xray_customeevent` builtin that gets translated to IR calls to the correct intrinsic. The default implementation of this is a no-op function. The codegen side of this follows the following logic:
- When `-fxray-instrument` is not provided in the driver, we elide all calls to `__xray_customevent`. - When `-fxray-instrument` is enabled and a function is marked as "never instrumented", we elide all calls to `__xray_customevent` in that function; if either marked as "always instrumented" or subject to threshold-based instrumentation, we emit a call to the `llvm.xray.customevent` intrinsic from LLVM for each `__xray_customevent` occurrence in the function. This change depends on https://reviews.llvm.org/D27503 (to land in LLVM first). https://reviews.llvm.org/D30018 Files: include/clang/Basic/Builtins.def lib/CodeGen/CGBuiltin.cpp lib/Headers/xrayintrin.h test/CodeGen/xray-customevent.cpp
Index: test/CodeGen/xray-customevent.cpp =================================================================== --- /dev/null +++ test/CodeGen/xray-customevent.cpp @@ -0,0 +1,28 @@ +// 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() { + static constexpr char kPhase[] = "instrument"; + __xray_customevent(kPhase, 10); + // CHECK: call void @llvm.xray.customevent(i8*{{.*}}, i8 10) +} + +// CHECK-LABEL: @_Z15neverInstrumentv +[[clang::xray_never_instrument]] void neverInstrument() { + static constexpr char kPhase[] = "never"; + __xray_customevent(kPhase, 5); + // CHECK-NOT: call void @llvm.xray.customevent(i8*{{.*}}, i8 5) +} + +// CHECK-LABEL: @_Z21conditionalInstrumenti +[[clang::xray_always_instrument]] void conditionalInstrument(int v) { + static constexpr char kTrue[] = "true"; + static constexpr char kUntrue[] = "untrue"; + if (v % 2) + __xray_customevent(kTrue, 4); + else + __xray_customevent(kUntrue, 6); + + // CHECK: call void @llvm.xray.customevent(i8*{{.*}}, i8 4) + // CHECK: call void @llvm.xray.customevent(i8*{{.*}}, i8 6) +} Index: lib/Headers/xrayintrin.h =================================================================== --- /dev/null +++ lib/Headers/xrayintrin.h @@ -0,0 +1,34 @@ +/*===---- xrayintrin.h - XRay intrinsics -----------------------------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __XRAYINTRIN_H +#define __XRAYINTRIN_H + +extern "C" { +inline void __xray_customevent(const char*, size_t) { + // Does nothing by design. The intent is the compiler's back-end will handle + // this particular intrinsic as special, and code-gen this appropriately. +} +} + +#endif // __XRAYINTRIN_H Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -2741,6 +2741,38 @@ return RValue::get(ConstantInt::get(ConvertType(E->getType()), Layout.size().getQuantity())); } + case Builtin::BI__xray_customevent: { + if (!this->ShouldXRayInstrumentFunction()) + return RValue::getIgnored(); + if (const auto *XRayAttr = + this->CurFuncDecl->getAttr<XRayInstrumentAttr>()) { + if (XRayAttr->neverXRayInstrument()) + return RValue::getIgnored(); + } + Function *F = CGM.getIntrinsic(Intrinsic::xray_customevent); + // FIXME: assert that the types of the arguments match the intrinsic's + // specification. + SmallVector<Value *, 2> Args; + auto FTy = F->getFunctionType(); + auto Arg0 = E->getArg(0); + auto Arg0Val = EmitScalarExpr(Arg0); + auto Arg0Ty = Arg0->getType(); + auto PTy0 = FTy->getParamType(0); + if (PTy0 != Arg0Val->getType()) { + if (Arg0Ty->isArrayType()) + Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); + else + Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); + } + Args.push_back(Arg0Val); + auto Arg1 = EmitScalarExpr(E->getArg(1)); + auto PTy1 = FTy->getParamType(1); + if (PTy1 != Arg1->getType()) + Arg1 = Builder.CreateTruncOrBitCast(Arg1, PTy1); + Args.push_back(Arg1); + Value *V = Builder.CreateCall(F, Args); + return RValue::get(V); + } } // If this is an alias for a lib function (e.g. __builtin_sin), emit Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -1407,6 +1407,9 @@ BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut") BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt") +// Builtins for XRay +BUILTIN(__xray_customevent, "vcC*z", "") + #undef BUILTIN #undef LIBBUILTIN #undef LANGBUILTIN
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits