diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 115 |
1 files changed, 71 insertions, 44 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index fab70b66d1d9..2199d7b58fb9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -495,12 +495,12 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { if (CurFnInfo->getMaxVectorWidth() > LargestVectorWidth) LargestVectorWidth = CurFnInfo->getMaxVectorWidth(); - // Add the required-vector-width attribute. This contains the max width from: + // Add the min-legal-vector-width attribute. This contains the max width from: // 1. min-vector-width attribute used in the source program. // 2. Any builtins used that have a vector width specified. // 3. Values passed in and out of inline assembly. // 4. Width of vector arguments and return types for this function. - // 5. Width of vector aguments and return types for functions called by this + // 5. Width of vector arguments and return types for functions called by this // function. if (getContext().getTargetInfo().getTriple().isX86()) CurFn->addFnAttr("min-legal-vector-width", @@ -572,11 +572,11 @@ llvm::ConstantInt * CodeGenFunction::getUBSanFunctionTypeHash(QualType Ty) const { // Remove any (C++17) exception specifications, to allow calling e.g. a // noexcept function through a non-noexcept pointer. - if (!isa<FunctionNoProtoType>(Ty)) + if (!Ty->isFunctionNoProtoType()) Ty = getContext().getFunctionTypeWithExceptionSpec(Ty, EST_None); std::string Mangled; llvm::raw_string_ostream Out(Mangled); - CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out, false); + CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out, false); return llvm::ConstantInt::get( CGM.Int32Ty, static_cast<uint32_t>(llvm::xxh3_64bits(Mangled))); } @@ -683,6 +683,19 @@ static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) { return true; } +bool CodeGenFunction::isInAllocaArgument(CGCXXABI &ABI, QualType Ty) { + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; +} + +bool CodeGenFunction::hasInAllocaArg(const CXXMethodDecl *MD) { + return getTarget().getTriple().getArch() == llvm::Triple::x86 && + getTarget().getCXXABI().isMicrosoft() && + llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) { + return isInAllocaArgument(CGM.getCXXABI(), P->getType()); + }); +} + /// Return the UBSan prologue signature for \p FD if one is available. static llvm::Constant *getPrologueSignature(CodeGenModule &CGM, const FunctionDecl *FD) { @@ -1108,11 +1121,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, Address(&*AI, ConvertType(RetTy), CurFnInfo->getReturnInfo().getIndirectAlign(), KnownNonNull); if (!CurFnInfo->getReturnInfo().getIndirectByVal()) { - ReturnValuePointer = - CreateDefaultAlignTempAlloca(Int8PtrTy, "result.ptr"); - Builder.CreateStore(Builder.CreatePointerBitCastOrAddrSpaceCast( - ReturnValue.getPointer(), Int8PtrTy), - ReturnValuePointer); + ReturnValuePointer = CreateDefaultAlignTempAlloca( + ReturnValue.getPointer()->getType(), "result.ptr"); + Builder.CreateStore(ReturnValue.getPointer(), ReturnValuePointer); } } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { @@ -1154,12 +1165,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, EmitFunctionProlog(*CurFnInfo, CurFn, Args); - if (isa_and_nonnull<CXXMethodDecl>(D) && - cast<CXXMethodDecl>(D)->isInstance()) { - CGM.getCXXABI().EmitInstanceFunctionProlog(*this); - const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); - if (MD->getParent()->isLambda() && - MD->getOverloadedOperator() == OO_Call) { + if (const CXXMethodDecl *MD = dyn_cast_if_present<CXXMethodDecl>(D); + MD && !MD->isStatic()) { + bool IsInLambda = + MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call; + if (MD->isImplicitObjectMemberFunction()) + CGM.getCXXABI().EmitInstanceFunctionProlog(*this); + if (IsInLambda) { // We're in a lambda; figure out the captures. MD->getParent()->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); @@ -1189,7 +1201,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, VLASizeMap[VAT->getSizeExpr()] = ExprArg; } } - } else { + } else if (MD->isImplicitObjectMemberFunction()) { // Not in a lambda; just use 'this' from the method. // FIXME: Should we generate a new load for each use of 'this'? The // fast register allocator would be happier... @@ -1202,11 +1214,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, SkippedChecks.set(SanitizerKind::ObjectSize, true); QualType ThisTy = MD->getThisType(); - // If this is the call operator of a lambda with no capture-default, it + // If this is the call operator of a lambda with no captures, it // may have a static invoker function, which may call this operator with // a null 'this' pointer. - if (isLambdaCallOperator(MD) && - MD->getParent()->getLambdaCaptureDefault() == LCD_None) + if (isLambdaCallOperator(MD) && MD->getParent()->isCapturelessLambda()) SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck( @@ -1249,11 +1260,6 @@ void CodeGenFunction::EmitFunctionBody(const Stmt *Body) { EmitCompoundStmtWithoutScope(*S); else EmitStmt(Body); - - // This is checked after emitting the function body so we know if there - // are any permitted infinite loops. - if (checkIfFunctionMustProgress()) - CurFn->addFnAttr(llvm::Attribute::MustProgress); } /// When instrumenting to collect profile data, the counts for some blocks @@ -1300,7 +1306,7 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, QualType ResTy = FD->getReturnType(); const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - if (MD && MD->isInstance()) { + if (MD && MD->isImplicitObjectMemberFunction()) { if (CGM.getCXXABI().HasThisReturn(GD)) ResTy = MD->getThisType(); else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) @@ -1325,7 +1331,7 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, auto *Implicit = ImplicitParamDecl::Create( getContext(), Param->getDeclContext(), Param->getLocation(), - /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamDecl::Other); + /*Id=*/nullptr, getContext().getSizeType(), ImplicitParamKind::Other); SizeArguments[Param] = Implicit; Args.push_back(Implicit); } @@ -1432,6 +1438,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, if (Body && isa_and_nonnull<CoroutineBodyStmt>(Body)) llvm::append_range(FnArgs, FD->parameters()); + // Ensure that the function adheres to the forward progress guarantee, which + // is required by certain optimizations. + if (checkIfFunctionMustProgress()) + CurFn->addFnAttr(llvm::Attribute::MustProgress); + // Generate the body of the function. PGO.assignRegionCounters(GD, CurFn); if (isa<CXXDestructorDecl>(FD)) @@ -1447,6 +1458,17 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // The lambda static invoker function is special, because it forwards or // clones the body of the function call operator (but is actually static). EmitLambdaStaticInvokeBody(cast<CXXMethodDecl>(FD)); + } else if (isa<CXXMethodDecl>(FD) && + isLambdaCallOperator(cast<CXXMethodDecl>(FD)) && + !FnInfo.isDelegateCall() && + cast<CXXMethodDecl>(FD)->getParent()->getLambdaStaticInvoker() && + hasInAllocaArg(cast<CXXMethodDecl>(FD))) { + // If emitting a lambda with static invoker on X86 Windows, change + // the call operator body. + // Make sure that this is a call operator with an inalloca arg and check + // for delegate call to make sure this is the original call op and not the + // new forwarding function for the static invoker. + EmitLambdaInAllocaCallOpBody(cast<CXXMethodDecl>(FD)); } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) && (cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() || cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) { @@ -2025,8 +2047,7 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { NullConstant, Twine()); CharUnits NullAlign = DestPtr.getAlignment(); NullVariable->setAlignment(NullAlign.getAsAlign()); - Address SrcPtr(Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy()), - Builder.getInt8Ty(), NullAlign); + Address SrcPtr(NullVariable, Builder.getInt8Ty(), NullAlign); if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal); @@ -2465,10 +2486,8 @@ llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Function *AnnotationFn, const AnnotateAttr *Attr) { SmallVector<llvm::Value *, 5> Args = { AnnotatedVal, - Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), - ConstGlobalsPtrTy), - Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), - ConstGlobalsPtrTy), + CGM.EmitAnnotationString(AnnotationStr), + CGM.EmitAnnotationUnit(Location), CGM.EmitAnnotationLineNo(Location), }; if (Attr) @@ -2478,15 +2497,10 @@ llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Function *AnnotationFn, void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute"); - // FIXME We create a new bitcast for every annotation because that's what - // llvm-gcc was doing. - unsigned AS = V->getType()->getPointerAddressSpace(); - llvm::Type *I8PtrTy = Builder.getInt8PtrTy(AS); for (const auto *I : D->specific_attrs<AnnotateAttr>()) EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation, - {I8PtrTy, CGM.ConstGlobalsPtrTy}), - Builder.CreateBitCast(V, I8PtrTy, V->getName()), - I->getAnnotation(), D->getLocation(), I); + {V->getType(), CGM.ConstGlobalsPtrTy}), + V, I->getAnnotation(), D->getLocation(), I); } Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, @@ -2571,10 +2585,15 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc, std::string MissingFeature; llvm::StringMap<bool> CallerFeatureMap; CGM.getContext().getFunctionFeatureMap(CallerFeatureMap, FD); + // When compiling in HipStdPar mode we have to be conservative in rejecting + // target specific features in the FE, and defer the possible error to the + // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is + // referenced by an accelerator executable function, we emit an error. + bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice; if (BuiltinID) { StringRef FeatureList(CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID)); if (!Builtin::evaluateRequiredTargetFeatures( - FeatureList, CallerFeatureMap)) { + FeatureList, CallerFeatureMap) && !IsHipStdPar) { CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature) << TargetDecl->getDeclName() << FeatureList; @@ -2607,7 +2626,7 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc, return false; } return true; - })) + }) && !IsHipStdPar) CGM.getDiags().Report(Loc, diag::err_function_needs_feature) << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature; } else if (!FD->isMultiVersion() && FD->hasAttr<TargetAttr>()) { @@ -2616,7 +2635,8 @@ void CodeGenFunction::checkTargetFeatures(SourceLocation Loc, for (const auto &F : CalleeFeatureMap) { if (F.getValue() && (!CallerFeatureMap.lookup(F.getKey()) || - !CallerFeatureMap.find(F.getKey())->getValue())) + !CallerFeatureMap.find(F.getKey())->getValue()) && + !IsHipStdPar) CGM.getDiags().Report(Loc, diag::err_function_needs_feature) << FD->getDeclName() << TargetDecl->getDeclName() << F.getKey(); } @@ -2658,8 +2678,15 @@ llvm::Value *CodeGenFunction::FormX86ResolverCondition( const MultiVersionResolverOption &RO) { llvm::Value *Condition = nullptr; - if (!RO.Conditions.Architecture.empty()) - Condition = EmitX86CpuIs(RO.Conditions.Architecture); + if (!RO.Conditions.Architecture.empty()) { + StringRef Arch = RO.Conditions.Architecture; + // If arch= specifies an x86-64 micro-architecture level, test the feature + // with __builtin_cpu_supports, otherwise use __builtin_cpu_is. + if (Arch.starts_with("x86-64")) + Condition = EmitX86CpuSupports({Arch}); + else + Condition = EmitX86CpuIs(Arch); + } if (!RO.Conditions.Features.empty()) { llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features); |
