2929#include " clang/Basic/TargetInfo.h"
3030#include " clang/Frontend/FrontendDiagnostic.h"
3131#include " llvm/Analysis/AssumptionCache.h"
32+ #include " llvm/Analysis/ValueTracking.h"
33+ #include " llvm/IR/Constants.h"
34+ #include " llvm/IR/DataLayout.h"
3235#include " llvm/IR/InlineAsm.h"
3336#include " llvm/IR/Instruction.h"
3437#include " llvm/IR/IntrinsicInst.h"
@@ -2321,14 +2324,40 @@ static RValue EmitCheckedUnsignedMultiplySignedResult(
23212324 CodeGenFunction &CGF, const clang::Expr *Op1, WidthAndSignedness Op1Info,
23222325 const clang::Expr *Op2, WidthAndSignedness Op2Info,
23232326 const clang::Expr *ResultArg, QualType ResultQTy,
2324- WidthAndSignedness ResultInfo) {
2327+ WidthAndSignedness ResultInfo, SourceLocation Loc ) {
23252328 assert (isSpecialUnsignedMultiplySignedResult (
23262329 Builtin::BI__builtin_mul_overflow, Op1Info, Op2Info, ResultInfo) &&
23272330 " Cannot specialize this multiply" );
23282331
2332+ clang::QualType Op1QTy = Op1->getType ();
2333+ clang::QualType Op2QTy = Op2->getType ();
2334+ bool Op1IsCap = Op1QTy->isCHERICapabilityType (CGF.getContext ());
2335+ bool Op2IsCap = Op2QTy->isCHERICapabilityType (CGF.getContext ());
2336+ bool ResultIsCap = ResultQTy->isCHERICapabilityType (CGF.getContext ());
2337+
23292338 llvm::Value *V1 = CGF.EmitScalarExpr (Op1);
23302339 llvm::Value *V2 = CGF.EmitScalarExpr (Op2);
23312340
2341+ llvm::Value *ProvenanceCap = nullptr ;
2342+ if (ResultIsCap) {
2343+ bool Op1NoProvenance =
2344+ !Op1IsCap || Op1QTy->hasAttr (attr::CHERINoProvenance);
2345+ bool Op2NoProvenance =
2346+ !Op2IsCap || Op2QTy->hasAttr (attr::CHERINoProvenance);
2347+ if (Op1NoProvenance && Op2NoProvenance)
2348+ ProvenanceCap = llvm::ConstantPointerNull::get (CGF.Int8CheriCapTy );
2349+ else if (Op1NoProvenance)
2350+ ProvenanceCap = V2;
2351+ else
2352+ ProvenanceCap = V1;
2353+ }
2354+
2355+ if (Op1IsCap)
2356+ V1 = CGF.getCapabilityIntegerValue (V1);
2357+
2358+ if (Op2IsCap)
2359+ V2 = CGF.getCapabilityIntegerValue (V2);
2360+
23322361 llvm::Value *HasOverflow;
23332362 llvm::Value *Result = EmitOverflowIntrinsic (
23342363 CGF, Intrinsic::umul_with_overflow, V1, V2, HasOverflow);
@@ -2342,6 +2371,9 @@ static RValue EmitCheckedUnsignedMultiplySignedResult(
23422371 llvm::Value *IntMaxOverflow = CGF.Builder .CreateICmpUGT (Result, IntMaxValue);
23432372 HasOverflow = CGF.Builder .CreateOr (HasOverflow, IntMaxOverflow);
23442373
2374+ if (ResultIsCap)
2375+ Result = CGF.setCapabilityIntegerValue (ProvenanceCap, Result, Loc);
2376+
23452377 bool isVolatile =
23462378 ResultArg->getType ()->getPointeeType ().isVolatileQualified ();
23472379 Address ResultPtr = CGF.EmitPointerWithAlignment (ResultArg);
@@ -2362,23 +2394,50 @@ static bool isSpecialMixedSignMultiply(unsigned BuiltinID,
23622394
23632395// / Emit a checked mixed-sign multiply. This is a cheaper specialization of
23642396// / the generic checked-binop irgen.
2365- static RValue
2366- EmitCheckedMixedSignMultiply (CodeGenFunction &CGF, const clang::Expr *Op1,
2367- WidthAndSignedness Op1Info, const clang::Expr *Op2,
2368- WidthAndSignedness Op2Info,
2369- const clang::Expr *ResultArg, QualType ResultQTy,
2370- WidthAndSignedness ResultInfo) {
2397+ static RValue EmitCheckedMixedSignMultiply (
2398+ CodeGenFunction &CGF, const clang::Expr *Op1, WidthAndSignedness Op1Info,
2399+ const clang::Expr *Op2, WidthAndSignedness Op2Info,
2400+ const clang::Expr *ResultArg, QualType ResultQTy,
2401+ WidthAndSignedness ResultInfo, SourceLocation Loc) {
23712402 assert (isSpecialMixedSignMultiply (Builtin::BI__builtin_mul_overflow, Op1Info,
23722403 Op2Info, ResultInfo) &&
23732404 " Not a mixed-sign multipliction we can specialize" );
23742405
2406+ QualType Op1QTy = Op1->getType ();
2407+ QualType Op2QTy = Op2->getType ();
2408+ bool Op1IsCap = Op1QTy->isCHERICapabilityType (CGF.getContext ());
2409+ bool Op2IsCap = Op2QTy->isCHERICapabilityType (CGF.getContext ());
2410+ bool ResultIsCap = ResultQTy->isCHERICapabilityType (CGF.getContext ());
2411+
23752412 // Emit the signed and unsigned operands.
23762413 const clang::Expr *SignedOp = Op1Info.Signed ? Op1 : Op2;
23772414 const clang::Expr *UnsignedOp = Op1Info.Signed ? Op2 : Op1;
23782415 llvm::Value *Signed = CGF.EmitScalarExpr (SignedOp);
23792416 llvm::Value *Unsigned = CGF.EmitScalarExpr (UnsignedOp);
23802417 unsigned SignedOpWidth = Op1Info.Signed ? Op1Info.Width : Op2Info.Width ;
23812418 unsigned UnsignedOpWidth = Op1Info.Signed ? Op2Info.Width : Op1Info.Width ;
2419+ bool SignedIsCap = Op1Info.Signed ? Op1IsCap : Op2IsCap;
2420+ bool UnsignedIsCap = Op1Info.Signed ? Op2IsCap : Op1IsCap;
2421+
2422+ llvm::Value *ProvenanceCap = nullptr ;
2423+ if (ResultIsCap) {
2424+ bool Op1NoProvenance =
2425+ !Op1IsCap || Op1QTy->hasAttr (attr::CHERINoProvenance);
2426+ bool Op2NoProvenance =
2427+ !Op2IsCap || Op2QTy->hasAttr (attr::CHERINoProvenance);
2428+ if (Op1NoProvenance && Op2NoProvenance)
2429+ ProvenanceCap = llvm::ConstantPointerNull::get (CGF.Int8CheriCapTy );
2430+ else if (Op1NoProvenance)
2431+ ProvenanceCap = Op1Info.Signed ? Unsigned : Signed;
2432+ else
2433+ ProvenanceCap = Op1Info.Signed ? Signed : Unsigned;
2434+ }
2435+
2436+ if (SignedIsCap)
2437+ Signed = CGF.getCapabilityIntegerValue (Signed);
2438+
2439+ if (UnsignedIsCap)
2440+ Unsigned = CGF.getCapabilityIntegerValue (Unsigned);
23822441
23832442 // One of the operands may be smaller than the other. If so, [s|z]ext it.
23842443 if (SignedOpWidth < UnsignedOpWidth)
@@ -2389,7 +2448,9 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
23892448 llvm::Type *OpTy = Signed->getType ();
23902449 llvm::Value *Zero = llvm::Constant::getNullValue (OpTy);
23912450 Address ResultPtr = CGF.EmitPointerWithAlignment (ResultArg);
2392- llvm::Type *ResTy = CGF.getTypes ().ConvertType (ResultQTy);
2451+ llvm::Type *ResTy = ResultIsCap ? llvm::IntegerType::get (CGF.getLLVMContext (),
2452+ ResultInfo.Width )
2453+ : CGF.getTypes ().ConvertType (ResultQTy);
23932454 unsigned OpWidth = std::max (Op1Info.Width , Op2Info.Width );
23942455
23952456 // Take the absolute value of the signed operand.
@@ -2428,8 +2489,7 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
24282489 IsNegative, CGF.Builder .CreateIsNotNull (UnsignedResult));
24292490 Overflow = CGF.Builder .CreateOr (UnsignedOverflow, Underflow);
24302491 if (ResultInfo.Width < OpWidth) {
2431- auto IntMax =
2432- llvm::APInt::getMaxValue (ResultInfo.Width ).zext (OpWidth);
2492+ auto IntMax = llvm::APInt::getMaxValue (ResultInfo.Width ).zext (OpWidth);
24332493 llvm::Value *TruncOverflow = CGF.Builder .CreateICmpUGT (
24342494 UnsignedResult, llvm::ConstantInt::get (OpTy, IntMax));
24352495 Overflow = CGF.Builder .CreateOr (Overflow, TruncOverflow);
@@ -2443,6 +2503,9 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, const clang::Expr *Op1,
24432503 }
24442504 assert (Overflow && Result && " Missing overflow or result" );
24452505
2506+ if (ResultIsCap)
2507+ Result = CGF.setCapabilityIntegerValue (ProvenanceCap, Result, Loc);
2508+
24462509 bool isVolatile =
24472510 ResultArg->getType ()->getPointeeType ().isVolatileQualified ();
24482511 CGF.Builder .CreateStore (CGF.EmitToMemory (Result, ResultQTy), ResultPtr,
@@ -5495,13 +5558,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
54955558 const clang::Expr *RightArg = E->getArg (1 );
54965559 const clang::Expr *ResultArg = E->getArg (2 );
54975560
5561+ clang::QualType LeftQTy = LeftArg->getType ();
5562+ clang::QualType RightQTy = RightArg->getType ();
54985563 clang::QualType ResultQTy =
54995564 ResultArg->getType ()->castAs <PointerType>()->getPointeeType ();
55005565
5566+ bool LeftIsCap = LeftQTy->isCHERICapabilityType (CGM.getContext ());
5567+ bool RightIsCap = RightQTy->isCHERICapabilityType (CGM.getContext ());
5568+ bool ResultIsCap = ResultQTy->isCHERICapabilityType (CGM.getContext ());
55015569 WidthAndSignedness LeftInfo =
5502- getIntegerWidthAndSignedness (CGM.getContext (), LeftArg-> getType () );
5570+ getIntegerWidthAndSignedness (CGM.getContext (), LeftQTy );
55035571 WidthAndSignedness RightInfo =
5504- getIntegerWidthAndSignedness (CGM.getContext (), RightArg-> getType () );
5572+ getIntegerWidthAndSignedness (CGM.getContext (), RightQTy );
55055573 WidthAndSignedness ResultInfo =
55065574 getIntegerWidthAndSignedness (CGM.getContext (), ResultQTy);
55075575
@@ -5510,44 +5578,78 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
55105578 if (isSpecialMixedSignMultiply (BuiltinID, LeftInfo, RightInfo, ResultInfo))
55115579 return EmitCheckedMixedSignMultiply (*this , LeftArg, LeftInfo, RightArg,
55125580 RightInfo, ResultArg, ResultQTy,
5513- ResultInfo);
5581+ ResultInfo, E-> getExprLoc () );
55145582
55155583 if (isSpecialUnsignedMultiplySignedResult (BuiltinID, LeftInfo, RightInfo,
55165584 ResultInfo))
55175585 return EmitCheckedUnsignedMultiplySignedResult (
55185586 *this , LeftArg, LeftInfo, RightArg, RightInfo, ResultArg, ResultQTy,
5519- ResultInfo);
5587+ ResultInfo, E-> getExprLoc () );
55205588
55215589 WidthAndSignedness EncompassingInfo =
55225590 EncompassingIntegerType ({LeftInfo, RightInfo, ResultInfo});
55235591
55245592 llvm::Type *EncompassingLLVMTy =
55255593 llvm::IntegerType::get (CGM.getLLVMContext (), EncompassingInfo.Width );
55265594
5527- llvm::Type *ResultLLVMTy = CGM.getTypes ().ConvertType (ResultQTy);
5595+ llvm::Type *ResultLLVMTy =
5596+ ResultIsCap
5597+ ? llvm::IntegerType::get (CGM.getLLVMContext (), ResultInfo.Width )
5598+ : CGM.getTypes ().ConvertType (ResultQTy);
55285599
55295600 Intrinsic::ID IntrinsicId;
5601+ bool Commutative;
55305602 switch (BuiltinID) {
55315603 default :
55325604 llvm_unreachable (" Unknown overflow builtin id." );
55335605 case Builtin::BI__builtin_add_overflow:
55345606 IntrinsicId = EncompassingInfo.Signed ? Intrinsic::sadd_with_overflow
55355607 : Intrinsic::uadd_with_overflow;
5608+ Commutative = true ;
55365609 break ;
55375610 case Builtin::BI__builtin_sub_overflow:
55385611 IntrinsicId = EncompassingInfo.Signed ? Intrinsic::ssub_with_overflow
55395612 : Intrinsic::usub_with_overflow;
5613+ Commutative = false ;
55405614 break ;
55415615 case Builtin::BI__builtin_mul_overflow:
55425616 IntrinsicId = EncompassingInfo.Signed ? Intrinsic::smul_with_overflow
55435617 : Intrinsic::umul_with_overflow;
5618+ Commutative = true ;
55445619 break ;
55455620 }
55465621
55475622 llvm::Value *Left = EmitScalarExpr (LeftArg);
55485623 llvm::Value *Right = EmitScalarExpr (RightArg);
55495624 Address ResultPtr = EmitPointerWithAlignment (ResultArg);
55505625
5626+ llvm::Value *ProvenanceCap = nullptr ;
5627+ if (ResultIsCap) {
5628+ if (!Commutative) {
5629+ if (LeftIsCap)
5630+ ProvenanceCap = Left;
5631+ else
5632+ ProvenanceCap = llvm::ConstantPointerNull::get (Int8CheriCapTy);
5633+ } else {
5634+ bool LeftNoProvenance =
5635+ !LeftIsCap || LeftQTy->hasAttr (attr::CHERINoProvenance);
5636+ bool RightNoProvenance =
5637+ !RightIsCap || RightQTy->hasAttr (attr::CHERINoProvenance);
5638+ if (LeftNoProvenance && RightNoProvenance)
5639+ ProvenanceCap = llvm::ConstantPointerNull::get (Int8CheriCapTy);
5640+ else if (LeftNoProvenance)
5641+ ProvenanceCap = Right;
5642+ else
5643+ ProvenanceCap = Left;
5644+ }
5645+ }
5646+
5647+ if (LeftIsCap)
5648+ Left = getCapabilityIntegerValue (Left);
5649+
5650+ if (RightIsCap)
5651+ Right = getCapabilityIntegerValue (Right);
5652+
55515653 // Extend each operand to the encompassing type.
55525654 Left = Builder.CreateIntCast (Left, EncompassingLLVMTy, LeftInfo.Signed );
55535655 Right = Builder.CreateIntCast (Right, EncompassingLLVMTy, RightInfo.Signed );
@@ -5572,6 +5674,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
55725674 Result = ResultTrunc;
55735675 }
55745676
5677+ if (ResultIsCap)
5678+ Result =
5679+ setCapabilityIntegerValue (ProvenanceCap, Result, E->getExprLoc ());
5680+
55755681 // Finally, store the result using the pointer.
55765682 bool isVolatile =
55775683 ResultArg->getType ()->getPointeeType ().isVolatileQualified ();
0 commit comments