Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -1455,6 +1455,7 @@ // 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") Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -281,6 +281,9 @@ 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 @@ #undef VALUE_LANGOPT #undef COMPATIBLE_VALUE_LANGOPT #undef BENIGN_VALUE_LANGOPT - Index: include/clang/Basic/XRayInstr.h =================================================================== --- include/clang/Basic/XRayInstr.h +++ include/clang/Basic/XRayInstr.h @@ -31,13 +31,15 @@ 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 Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1119,6 +1119,12 @@ def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group, Flags<[CC1Option]>; +def fxray_always_emit_typedevents : Flag<["-"], "fxray-always-emit-typedevents">, 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, + Flags<[CC1Option]>; + def fxray_link_deps : Flag<["-"], "fxray-link-deps">, Group, Flags<[CC1Option]>, HelpText<"Tells clang to add the link dependencies for XRay.">; Index: include/clang/Driver/XRayArgs.h =================================================================== --- include/clang/Driver/XRayArgs.h +++ include/clang/Driver/XRayArgs.h @@ -29,6 +29,7 @@ bool XRayInstrument = false; int InstructionThreshold = 200; bool XRayAlwaysEmitCustomEvents = false; + bool XRayAlwaysEmitTypedEvents = false; bool XRayRT = true; public: Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -95,6 +95,9 @@ ///< 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) Index: lib/Basic/XRayInstr.cpp =================================================================== --- lib/Basic/XRayInstr.cpp +++ lib/Basic/XRayInstr.cpp @@ -21,6 +21,7 @@ .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; Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -3369,6 +3369,44 @@ 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()) + 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( Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -1804,6 +1804,10 @@ /// 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); Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -13,9 +13,9 @@ #include "CodeGenFunction.h" #include "CGBlocks.h" -#include "CGCleanup.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" +#include "CGCleanup.h" #include "CGDebugInfo.h" #include "CGOpenMPRuntime.h" #include "CodeGenModule.h" @@ -122,9 +122,8 @@ CGM.getOpenMPRuntime().functionFinished(*this); } -CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, - LValueBaseInfo *BaseInfo, - TBAAAccessInfo *TBAAInfo) { +CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment( + QualType T, LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) { return getNaturalTypeAlignment(T->getPointeeType(), BaseInfo, TBAAInfo, /* forPointeeType= */ true); } @@ -187,8 +186,8 @@ /// Given a value of type T* that may not be to a complete object, /// construct an l-value with the natural pointee alignment of T. -LValue -CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { +LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, + QualType T) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; CharUnits Align = getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, @@ -196,7 +195,6 @@ return MakeAddrLValue(Address(V, Align), T, BaseInfo, TBAAInfo); } - llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); } @@ -282,7 +280,7 @@ // cleans up functions which started with a unified return block. if (ReturnBlock.getBlock()->hasOneUse()) { llvm::BranchInst *BI = - dyn_cast(*ReturnBlock.getBlock()->user_begin()); + dyn_cast(*ReturnBlock.getBlock()->user_begin()); if (BI && BI->isUnconditional() && BI->getSuccessor(0) == ReturnBlock.getBlock()) { // Record/return the DebugLoc of the simple 'return' expression to be used @@ -304,7 +302,8 @@ } static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) { - if (!BB) return; + if (!BB) + return; if (!BB->use_empty()) return CGF.CurFn->getBasicBlockList().push_back(BB); delete BB; @@ -314,9 +313,9 @@ assert(BreakContinueStack.empty() && "mismatched push/pop in break/continue stack!"); - bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 - && NumSimpleReturnExprs == NumReturnExprs - && ReturnBlock.getBlock()->use_empty(); + bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 && + NumSimpleReturnExprs == NumReturnExprs && + ReturnBlock.getBlock()->use_empty(); // Usually the return expression is evaluated before the cleanup // code. If the function contains only a simple return statement, // such as a constant, the location before the cleanup code becomes @@ -375,8 +374,7 @@ EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc, EndLoc); EmitEndEHSpec(CurCodeDecl); - assert(EHStack.empty() && - "did not remove all scopes from cleanup stack!"); + assert(EHStack.empty() && "did not remove all scopes from cleanup stack!"); // If someone did an indirect goto, emit the indirect goto block at the end of // the function. @@ -425,7 +423,7 @@ if (CGM.getCodeGenOpts().EmitDeclMetadata) EmitDeclMetadata(); - for (SmallVectorImpl >::iterator + for (SmallVectorImpl>::iterator I = DeferredReplacements.begin(), E = DeferredReplacements.end(); I != E; ++I) { @@ -466,7 +464,7 @@ } /// 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 +472,13 @@ 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) { @@ -511,7 +516,7 @@ "decoded_addr"); } -static void removeImageAccessQualifier(std::string& TyName) { +static void removeImageAccessQualifier(std::string &TyName) { std::string ReadOnlyQual("__read_only"); std::string::size_type ReadOnlyPos = TyName.find(ReadOnlyQual); if (ReadOnlyPos != std::string::npos) @@ -539,10 +544,14 @@ // (basically all single AS CPUs). static unsigned ArgInfoAddressSpace(LangAS AS) { switch (AS) { - case LangAS::opencl_global: return 1; - case LangAS::opencl_constant: return 2; - case LangAS::opencl_local: return 3; - case LangAS::opencl_generic: return 4; // Not in SPIR 2.0 specs. + case LangAS::opencl_global: + return 1; + case LangAS::opencl_constant: + return 2; + case LangAS::opencl_local: + return 3; + case LangAS::opencl_generic: + return 4; // Not in SPIR 2.0 specs. default: return 0; // Assume private. } @@ -587,8 +596,8 @@ QualType pointeeTy = ty->getPointeeType(); // Get address qualifier. - addressQuals.push_back(llvm::ConstantAsMetadata::get(Builder.getInt32( - ArgInfoAddressSpace(pointeeTy.getAddressSpace())))); + addressQuals.push_back(llvm::ConstantAsMetadata::get( + Builder.getInt32(ArgInfoAddressSpace(pointeeTy.getAddressSpace())))); // Get argument type name. std::string typeName = @@ -597,7 +606,7 @@ // Turn "unsigned type" to "utype" std::string::size_type pos = typeName.find("unsigned"); if (pointeeTy.isCanonical() && pos != std::string::npos) - typeName.erase(pos+1, 8); + typeName.erase(pos + 1, 8); argTypeNames.push_back(llvm::MDString::get(Context, typeName)); @@ -609,7 +618,7 @@ // Turn "unsigned type" to "utype" pos = baseTypeName.find("unsigned"); if (pos != std::string::npos) - baseTypeName.erase(pos+1, 8); + baseTypeName.erase(pos + 1, 8); argBaseTypeNames.push_back(llvm::MDString::get(Context, baseTypeName)); @@ -633,24 +642,28 @@ // Get argument type name. std::string typeName; if (isPipe) - typeName = ty.getCanonicalType()->getAs()->getElementType() - .getAsString(Policy); + typeName = ty.getCanonicalType() + ->getAs() + ->getElementType() + .getAsString(Policy); else typeName = ty.getUnqualifiedType().getAsString(Policy); // Turn "unsigned type" to "utype" std::string::size_type pos = typeName.find("unsigned"); if (ty.isCanonical() && pos != std::string::npos) - typeName.erase(pos+1, 8); + typeName.erase(pos + 1, 8); std::string baseTypeName; if (isPipe) - baseTypeName = ty.getCanonicalType()->getAs() - ->getElementType().getCanonicalType() - .getAsString(Policy); + baseTypeName = ty.getCanonicalType() + ->getAs() + ->getElementType() + .getCanonicalType() + .getAsString(Policy); else baseTypeName = - ty.getUnqualifiedType().getCanonicalType().getAsString(Policy); + ty.getUnqualifiedType().getCanonicalType().getAsString(Policy); // Remove access qualifiers on images // (as they are inseparable from type in clang implementation, @@ -666,7 +679,7 @@ // Turn "unsigned type" to "utype" pos = baseTypeName.find("unsigned"); if (pos != std::string::npos) - baseTypeName.erase(pos+1, 8); + baseTypeName.erase(pos + 1, 8); argBaseTypeNames.push_back(llvm::MDString::get(Context, baseTypeName)); @@ -677,7 +690,7 @@ argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals)); // Get image and pipe access qualifier: - if (ty->isImageType()|| ty->isPipeType()) { + if (ty->isImageType() || ty->isPipeType()) { const Decl *PDecl = parm; if (auto *TD = dyn_cast(ty)) PDecl = TD->getDecl(); @@ -699,20 +712,17 @@ llvm::MDNode::get(Context, addressQuals)); Fn->setMetadata("kernel_arg_access_qual", llvm::MDNode::get(Context, accessQuals)); - Fn->setMetadata("kernel_arg_type", - llvm::MDNode::get(Context, argTypeNames)); + Fn->setMetadata("kernel_arg_type", llvm::MDNode::get(Context, argTypeNames)); Fn->setMetadata("kernel_arg_base_type", llvm::MDNode::get(Context, argBaseTypeNames)); Fn->setMetadata("kernel_arg_type_qual", llvm::MDNode::get(Context, argTypeQuals)); if (CGM.getCodeGenOpts().EmitOpenCLArgMetadata) - Fn->setMetadata("kernel_arg_name", - llvm::MDNode::get(Context, argNames)); + Fn->setMetadata("kernel_arg_name", llvm::MDNode::get(Context, argNames)); } void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, - llvm::Function *Fn) -{ + llvm::Function *Fn) { if (!FD->hasAttr()) return; @@ -740,7 +750,8 @@ llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, AttrMDArgs)); + Fn->setMetadata("work_group_size_hint", + llvm::MDNode::get(Context, AttrMDArgs)); } if (const ReqdWorkGroupSizeAttr *A = FD->getAttr()) { @@ -748,7 +759,8 @@ llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, AttrMDArgs)); + Fn->setMetadata("reqd_work_group_size", + llvm::MDNode::get(Context, AttrMDArgs)); } if (const OpenCLIntelReqdSubGroupSizeAttr *A = @@ -761,7 +773,7 @@ } /// Determine whether the function F ends with a return stmt. -static bool endsWithReturn(const Decl* F) { +static bool endsWithReturn(const Decl *F) { const Stmt *Body = nullptr; if (auto *FD = dyn_cast_or_null(F)) Body = FD->getBody(); @@ -810,8 +822,7 @@ return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM); } -void CodeGenFunction::StartFunction(GlobalDecl GD, - QualType RetTy, +void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, @@ -866,7 +877,8 @@ // Apply sanitizer attributes to the function. if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeAddress); - if (SanOpts.hasOneOf(SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress)) + if (SanOpts.hasOneOf(SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); if (SanOpts.has(SanitizerKind::Thread)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); @@ -888,7 +900,8 @@ IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0); if (OMD->getMethodFamily() == OMF_dealloc || OMD->getMethodFamily() == OMF_initialize || - (OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) { + (OMD->getSelector().isUnarySelector() && + II->isStr(".cxx_destruct"))) { markAsIgnoreThreadCheckingAtRuntime(Fn); } } else if (const auto *FD = dyn_cast_or_null(D)) { @@ -949,9 +962,8 @@ if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) { // Remove any (C++17) exception specifications, to allow calling e.g. a // noexcept function through a non-noexcept pointer. - auto ProtoTy = - getContext().getFunctionTypeWithExceptionSpec(FD->getType(), - EST_None); + auto ProtoTy = getContext().getFunctionTypeWithExceptionSpec( + FD->getType(), EST_None); llvm::Constant *FTRTTIConst = CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); llvm::Constant *FTRTTIConstEncoded = @@ -1079,8 +1091,7 @@ // Tell the epilog emitter to autorelease the result. We do this // now so that various specialized functions can suppress it // during their IR-generation. - if (getLangOpts().ObjCAutoRefCount && - !CurFnInfo->isReturnsRetained() && + if (getLangOpts().ObjCAutoRefCount && !CurFnInfo->isReturnsRetained() && RetTy->isObjCRetainableType()) AutoreleaseResult = true; } @@ -1098,8 +1109,7 @@ if (D && isa(D) && cast(D)->isInstance()) { CGM.getCXXABI().EmitInstanceFunctionProlog(*this); const CXXMethodDecl *MD = cast(D); - if (MD->getParent()->isLambda() && - MD->getOverloadedOperator() == OO_Call) { + if (MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call) { // We're in a lambda; figure out the captures. MD->getParent()->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); @@ -1110,21 +1120,24 @@ // Get the lvalue for the field (which is a copy of the enclosing object // or contains the address of the enclosing object). - LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); + LValue ThisFieldLValue = + EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its address. + // If the enclosing object was captured by value, just use its + // address. CXXThisValue = ThisFieldLValue.getAddress().getPointer(); } else { // Load the lvalue pointed to by the field, since '*this' was captured // by reference. - CXXThisValue = - EmitLoadOfLValue(ThisFieldLValue, SourceLocation()).getScalarVal(); + CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) + .getScalarVal(); } } for (auto *FD : MD->getParent()->fields()) { if (FD->hasCapturedVLAType()) { - auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD), - SourceLocation()).getScalarVal(); + auto *ExprArg = + EmitLoadOfLValue(EmitLValueForLambdaField(FD), SourceLocation()) + .getScalarVal(); auto VAT = FD->getCapturedVLAType(); VLASizeMap[VAT->getSizeExpr()] = ExprArg; } @@ -1159,8 +1172,8 @@ // If any of the arguments have a variably modified type, make sure to // emit the type size. - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); - i != e; ++i) { + for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; + ++i) { const VarDecl *VD = *i; // Dig out the type as written from ParmVarDecls; it's unclear whether @@ -1217,7 +1230,8 @@ static void TryMarkNoThrow(llvm::Function *F) { // LLVM treats 'nounwind' on a function as part of the type, so we // can't do this on functions that can be overwritten. - if (F->isInterposable()) return; + if (F->isInterposable()) + return; for (llvm::BasicBlock &BB : *F) for (llvm::Instruction &I : BB) @@ -1333,8 +1347,7 @@ EmitDestructorBody(Args); else if (isa(FD)) EmitConstructorBody(Args); - else if (getLangOpts().CUDA && - !getLangOpts().CUDAIsDevice && + else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice && FD->hasAttr()) CGM.getCUDARuntime().emitDeviceStub(*this, Args); else if (isa(FD) && @@ -1394,7 +1407,8 @@ /// that we can just remove the code. bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { // Null statement, not a label! - if (!S) return false; + if (!S) + return false; // If this is a label, we have to emit the code, consider something like: // if (0) { ... foo: bar(); } goto foo; @@ -1426,7 +1440,8 @@ /// inside of it, this is fine. bool CodeGenFunction::containsBreak(const Stmt *S) { // Null statement, not a label! - if (!S) return false; + if (!S) + return false; // If this is a switch or loop that defines its own break scope, then we can // include it and anything inside of it. @@ -1446,7 +1461,8 @@ } bool CodeGenFunction::mightAddDeclToScope(const Stmt *S) { - if (!S) return false; + if (!S) + return false; // Some statement kinds add a scope and thus never add a decl to the current // scope. Note, this list is longer than the list of statements that might @@ -1492,17 +1508,15 @@ // to bool. llvm::APSInt Int; if (!Cond->EvaluateAsInt(Int, getContext())) - return false; // Not foldable, not integer or not fully evaluatable. + return false; // Not foldable, not integer or not fully evaluatable. if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond)) - return false; // Contains a label. + return false; // Contains a label. ResultInt = Int; return true; } - - /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if /// statement) to the specified blocks. Based on the condition, this might try /// to simplify the codegen of the conditional based on the branch. @@ -1670,7 +1684,7 @@ // br(c ? throw x : y, t, f) -> br(c, br(throw x, t, f), br(y, t, f) // Fold this to: // br(c, throw x, br(y, t, f)) - EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/false); + EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/ false); return; } @@ -1721,13 +1735,12 @@ CGBuilderTy &Builder = CGF.Builder; CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType); - llvm::Value *baseSizeInChars - = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); + llvm::Value *baseSizeInChars = + llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); - Address begin = - Builder.CreateElementBitCast(dest, CGF.Int8Ty, "vla.begin"); + Address begin = Builder.CreateElementBitCast(dest, CGF.Int8Ty, "vla.begin"); llvm::Value *end = - Builder.CreateInBoundsGEP(begin.getPointer(), sizeInChars, "vla.end"); + Builder.CreateInBoundsGEP(begin.getPointer(), sizeInChars, "vla.end"); llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); @@ -1740,8 +1753,7 @@ llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); cur->addIncoming(begin.getPointer(), originBB); - CharUnits curAlign = - dest.getAlignment().alignmentOfArrayElement(baseSize); + CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize); // memcpy the individual element bit-pattern. Builder.CreateMemCpy(Address(cur, curAlign), src, baseSizeInChars, @@ -1749,7 +1761,7 @@ // Go to the next element. llvm::Value *next = - Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next"); + Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next"); // Leave if that's the end of the VLA. llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone"); @@ -1759,8 +1771,7 @@ CGF.EmitBlock(contBB); } -void -CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { +void CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { // Ignore empty classes in C++. if (getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs()) { @@ -1782,9 +1793,8 @@ // Don't bother emitting a zero-byte memset. if (size.isZero()) { // But note that getTypeInfo returns 0 for a VLA. - if (const VariableArrayType *vlaType = - dyn_cast_or_null( - getContext().getAsArrayType(Ty))) { + if (const VariableArrayType *vlaType = dyn_cast_or_null( + getContext().getAsArrayType(Ty))) { auto VlaSize = getVLASize(vlaType); SizeVal = VlaSize.NumElts; CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type); @@ -1805,21 +1815,22 @@ // like -1, which happens to be the pattern used by member-pointers. if (!CGM.getTypes().isZeroInitializable(Ty)) { // For a VLA, emit a single element, then splat that over the VLA. - if (vla) Ty = getContext().getBaseElementType(vla); + if (vla) + Ty = getContext().getBaseElementType(vla); llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty); - llvm::GlobalVariable *NullVariable = - new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(), - /*isConstant=*/true, - llvm::GlobalVariable::PrivateLinkage, - NullConstant, Twine()); + llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable( + CGM.getModule(), NullConstant->getType(), + /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, NullConstant, + Twine()); CharUnits NullAlign = DestPtr.getAlignment(); NullVariable->setAlignment(NullAlign.getQuantity()); Address SrcPtr(Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy()), NullAlign); - if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal); + if (vla) + return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal); // Get and call the appropriate llvm.memcpy overload. Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, false); @@ -1846,13 +1857,14 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() { // If we already made the indirect branch for indirect goto, return its block. - if (IndirectBranch) return IndirectBranch->getParent(); + if (IndirectBranch) + return IndirectBranch->getParent(); CGBuilderTy TmpBuilder(*this, createBasicBlock("indirectgoto")); // Create the PHI node that indirect gotos will add entries to. - llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0, - "indirect.goto.dest"); + llvm::Value *DestVal = + TmpBuilder.CreatePHI(Int8PtrTy, 0, "indirect.goto.dest"); // Create the indirect branch instruction. IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal); @@ -1892,7 +1904,7 @@ // We have some number of constant-length arrays, so addr should // have LLVM type [M x [N x [...]]]*. Build a GEP that walks // down to the first element of addr. - SmallVector gepIndices; + SmallVector gepIndices; // GEP down to the array type. llvm::ConstantInt *zero = Builder.getInt32(0); @@ -1902,18 +1914,17 @@ QualType eltType; llvm::ArrayType *llvmArrayType = - dyn_cast(addr.getElementType()); + dyn_cast(addr.getElementType()); while (llvmArrayType) { assert(isa(arrayType)); - assert(cast(arrayType)->getSize().getZExtValue() - == llvmArrayType->getNumElements()); + assert(cast(arrayType)->getSize().getZExtValue() == + llvmArrayType->getNumElements()); gepIndices.push_back(zero); countFromCLAs *= llvmArrayType->getNumElements(); eltType = arrayType->getElementType(); - llvmArrayType = - dyn_cast(llvmArrayType->getElementType()); + llvmArrayType = dyn_cast(llvmArrayType->getElementType()); arrayType = getContext().getAsArrayType(arrayType->getElementType()); assert((!llvmArrayType || arrayType) && "LLVM and Clang types are out-of-synch"); @@ -1934,15 +1945,14 @@ addr = Builder.CreateElementBitCast(addr, baseType, "array.begin"); } else { // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP(addr.getPointer(), - gepIndices, "array.begin"), - addr.getAlignment()); + addr = Address( + Builder.CreateInBoundsGEP(addr.getPointer(), gepIndices, "array.begin"), + addr.getAlignment()); } baseType = eltType; - llvm::Value *numElements - = llvm::ConstantInt::get(SizeTy, countFromCLAs); + llvm::Value *numElements = llvm::ConstantInt::get(SizeTy, countFromCLAs); // If we had any VLA dimensions, factor them in. if (numVLAElements) @@ -1978,11 +1988,10 @@ } } while ((type = getContext().getAsVariableArrayType(elementType))); - return { numElements, elementType }; + return {numElements, elementType}; } -CodeGenFunction::VlaSizePair -CodeGenFunction::getVLAElements1D(QualType type) { +CodeGenFunction::VlaSizePair CodeGenFunction::getVLAElements1D(QualType type) { const VariableArrayType *vla = getContext().getAsVariableArrayType(type); assert(vla && "type was not a variable array type!"); return getVLAElements1D(vla); @@ -1993,7 +2002,7 @@ llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()]; assert(VlaSize && "no size for VLA!"); assert(VlaSize->getType() == SizeTy); - return { VlaSize, Vla->getElementType() }; + return {VlaSize, Vla->getElementType()}; } void CodeGenFunction::EmitVariablyModifiedType(QualType type) { @@ -2086,9 +2095,8 @@ SanitizerScope SanScope(this); llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType()); llvm::Constant *StaticArgs[] = { - EmitCheckSourceLocation(size->getLocStart()), - EmitCheckTypeDescriptor(size->getType()) - }; + EmitCheckSourceLocation(size->getLocStart()), + EmitCheckTypeDescriptor(size->getType())}; EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero), SanitizerKind::VLABound), SanitizerHandler::VLABoundNotPositive, StaticArgs, Size); @@ -2141,7 +2149,7 @@ } while (type->isVariablyModifiedType()); } -Address CodeGenFunction::EmitVAListRef(const Expr* E) { +Address CodeGenFunction::EmitVAListRef(const Expr *E) { if (getContext().getBuiltinVaListType()->isArrayType()) return EmitPointerWithAlignment(E); return EmitLValue(E).getAddress(); @@ -2165,9 +2173,11 @@ // is trunc(zext) folding, but if we add more, we can easily // extend this protection. - if (!rvalue.isScalar()) return PeepholeProtection(); + if (!rvalue.isScalar()) + return PeepholeProtection(); llvm::Value *value = rvalue.getScalarVal(); - if (!isa(value)) return PeepholeProtection(); + if (!isa(value)) + return PeepholeProtection(); // Just make an extra bitcast. assert(HaveInsertPoint()); @@ -2180,7 +2190,8 @@ } void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) { - if (!protection.Inst) return; + if (!protection.Inst) + return; // In theory, we could try to duplicate the peepholes now, but whatever. protection.Inst->eraseFromParent(); @@ -2191,11 +2202,10 @@ StringRef AnnotationStr, SourceLocation Location) { llvm::Value *Args[4] = { - AnnotatedVal, - Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy), - Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy), - CGM.EmitAnnotationLineNo(Location) - }; + AnnotatedVal, + Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy), + Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy), + CGM.EmitAnnotationLineNo(Location)}; return Builder.CreateCall(AnnotationFn, Args); } @@ -2214,8 +2224,8 @@ assert(D->hasAttr() && "no annotate attribute"); llvm::Value *V = Addr.getPointer(); llvm::Type *VTy = V->getType(); - llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, - CGM.Int8PtrTy); + llvm::Value *F = + CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, CGM.Int8PtrTy); for (const auto *I : D->specific_attrs()) { // FIXME Always emit the cast inst so we can differentiate between @@ -2230,7 +2240,7 @@ return Address(V, Addr.getAlignment()); } -CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { } +CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() {} CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF) : CGF(CGF) { Index: lib/Driver/XRayArgs.cpp =================================================================== --- lib/Driver/XRayArgs.cpp +++ lib/Driver/XRayArgs.cpp @@ -77,6 +77,10 @@ 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 @@ 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))); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -845,6 +845,8 @@ 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); @@ -2669,6 +2671,11 @@ 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); Index: test/CodeGen/xray-always-emit-typedevent.cpp =================================================================== --- /dev/null +++ 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) +} Index: test/CodeGen/xray-instrumentation-bundles.cpp =================================================================== --- test/CodeGen/xray-instrumentation-bundles.cpp +++ 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" {{.*}} Index: test/CodeGen/xray-typedevent.cpp =================================================================== --- /dev/null +++ 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) +}