@@ -507,9 +507,13 @@ static constexpr llvm::StringRef MagicRuntimeInterface[] = {
507
507
" __clang_Interpreter_SetValueWithAlloc" ,
508
508
" __clang_Interpreter_SetValueCopyArr" , " __ci_newtag" };
509
509
510
- bool Interpreter::FindRuntimeInterface () {
510
+ static std::unique_ptr<RuntimeInterfaceBuilder>
511
+ createInProcessRuntimeInterfaceBuilder (Interpreter &Interp, ASTContext &Ctx,
512
+ Sema &S);
513
+
514
+ std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface () {
511
515
if (llvm::all_of (ValuePrintingInfo, [](Expr *E) { return E != nullptr ; }))
512
- return true ;
516
+ return nullptr ;
513
517
514
518
Sema &S = getCompilerInstance ()->getSema ();
515
519
ASTContext &Ctx = S.getASTContext ();
@@ -528,120 +532,34 @@ bool Interpreter::FindRuntimeInterface() {
528
532
529
533
if (!LookupInterface (ValuePrintingInfo[NoAlloc],
530
534
MagicRuntimeInterface[NoAlloc]))
531
- return false ;
535
+ return nullptr ;
532
536
if (!LookupInterface (ValuePrintingInfo[WithAlloc],
533
537
MagicRuntimeInterface[WithAlloc]))
534
- return false ;
538
+ return nullptr ;
535
539
if (!LookupInterface (ValuePrintingInfo[CopyArray],
536
540
MagicRuntimeInterface[CopyArray]))
537
- return false ;
541
+ return nullptr ;
538
542
if (!LookupInterface (ValuePrintingInfo[NewTag],
539
543
MagicRuntimeInterface[NewTag]))
540
- return false ;
541
- return true ;
544
+ return nullptr ;
545
+
546
+ return createInProcessRuntimeInterfaceBuilder (*this , Ctx, S);
542
547
}
543
548
544
549
namespace {
545
550
546
- class RuntimeInterfaceBuilder
547
- : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> {
548
- clang::Interpreter &Interp;
551
+ class InterfaceKindVisitor
552
+ : public TypeVisitor<InterfaceKindVisitor, Interpreter::InterfaceKind> {
553
+ friend class InProcessRuntimeInterfaceBuilder ;
554
+
549
555
ASTContext &Ctx;
550
556
Sema &S;
551
557
Expr *E;
552
558
llvm::SmallVector<Expr *, 3 > Args;
553
559
554
560
public:
555
- RuntimeInterfaceBuilder (clang::Interpreter &In, ASTContext &C, Sema &SemaRef,
556
- Expr *VE, ArrayRef<Expr *> FixedArgs)
557
- : Interp(In), Ctx(C), S(SemaRef), E(VE) {
558
- // The Interpreter* parameter and the out parameter `OutVal`.
559
- for (Expr *E : FixedArgs)
560
- Args.push_back (E);
561
-
562
- // Get rid of ExprWithCleanups.
563
- if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
564
- E = EWC->getSubExpr ();
565
- }
566
-
567
- ExprResult getCall () {
568
- QualType Ty = E->getType ();
569
- QualType DesugaredTy = Ty.getDesugaredType (Ctx);
570
-
571
- // For lvalue struct, we treat it as a reference.
572
- if (DesugaredTy->isRecordType () && E->isLValue ()) {
573
- DesugaredTy = Ctx.getLValueReferenceType (DesugaredTy);
574
- Ty = Ctx.getLValueReferenceType (Ty);
575
- }
576
-
577
- Expr *TypeArg =
578
- CStyleCastPtrExpr (S, Ctx.VoidPtrTy , (uintptr_t )Ty.getAsOpaquePtr ());
579
- // The QualType parameter `OpaqueType`, represented as `void*`.
580
- Args.push_back (TypeArg);
581
-
582
- // We push the last parameter based on the type of the Expr. Note we need
583
- // special care for rvalue struct.
584
- Interpreter::InterfaceKind Kind = Visit (&*DesugaredTy);
585
- switch (Kind) {
586
- case Interpreter::InterfaceKind::WithAlloc:
587
- case Interpreter::InterfaceKind::CopyArray: {
588
- // __clang_Interpreter_SetValueWithAlloc.
589
- ExprResult AllocCall = S.ActOnCallExpr (
590
- /* Scope=*/ nullptr ,
591
- Interp.getValuePrintingInfo ()[Interpreter::InterfaceKind::WithAlloc],
592
- E->getBeginLoc (), Args, E->getEndLoc ());
593
- assert (!AllocCall.isInvalid () && " Can't create runtime interface call!" );
594
-
595
- TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo (Ty, SourceLocation ());
596
-
597
- // Force CodeGen to emit destructor.
598
- if (auto *RD = Ty->getAsCXXRecordDecl ()) {
599
- auto *Dtor = S.LookupDestructor (RD);
600
- Dtor->addAttr (UsedAttr::CreateImplicit (Ctx));
601
- Interp.getCompilerInstance ()->getASTConsumer ().HandleTopLevelDecl (
602
- DeclGroupRef (Dtor));
603
- }
604
-
605
- // __clang_Interpreter_SetValueCopyArr.
606
- if (Kind == Interpreter::InterfaceKind::CopyArray) {
607
- const auto *ConstantArrTy =
608
- cast<ConstantArrayType>(DesugaredTy.getTypePtr ());
609
- size_t ArrSize = Ctx.getConstantArrayElementCount (ConstantArrTy);
610
- Expr *ArrSizeExpr = IntegerLiteralExpr (Ctx, ArrSize);
611
- Expr *Args[] = {E, AllocCall.get (), ArrSizeExpr};
612
- return S.ActOnCallExpr (
613
- /* Scope *=*/ nullptr ,
614
- Interp
615
- .getValuePrintingInfo ()[Interpreter::InterfaceKind::CopyArray],
616
- SourceLocation (), Args, SourceLocation ());
617
- }
618
- Expr *Args[] = {
619
- AllocCall.get (),
620
- Interp.getValuePrintingInfo ()[Interpreter::InterfaceKind::NewTag]};
621
- ExprResult CXXNewCall = S.BuildCXXNew (
622
- E->getSourceRange (),
623
- /* UseGlobal=*/ true , /* PlacementLParen=*/ SourceLocation (), Args,
624
- /* PlacementRParen=*/ SourceLocation (),
625
- /* TypeIdParens=*/ SourceRange (), TSI->getType (), TSI, std::nullopt,
626
- E->getSourceRange (), E);
627
-
628
- assert (!CXXNewCall.isInvalid () &&
629
- " Can't create runtime placement new call!" );
630
-
631
- return S.ActOnFinishFullExpr (CXXNewCall.get (),
632
- /* DiscardedValue=*/ false );
633
- }
634
- // __clang_Interpreter_SetValueNoAlloc.
635
- case Interpreter::InterfaceKind::NoAlloc: {
636
- return S.ActOnCallExpr (
637
- /* Scope=*/ nullptr ,
638
- Interp.getValuePrintingInfo ()[Interpreter::InterfaceKind::NoAlloc],
639
- E->getBeginLoc (), Args, E->getEndLoc ());
640
- }
641
- default :
642
- llvm_unreachable (" Unhandled Interpreter::InterfaceKind" );
643
- }
644
- }
561
+ InterfaceKindVisitor (ASTContext &Ctx, Sema &S, Expr *E)
562
+ : Ctx(Ctx), S(S), E(E) {}
645
563
646
564
Interpreter::InterfaceKind VisitRecordType (const RecordType *Ty) {
647
565
return Interpreter::InterfaceKind::WithAlloc;
@@ -713,8 +631,124 @@ class RuntimeInterfaceBuilder
713
631
Args.push_back (CastedExpr.get ());
714
632
}
715
633
};
634
+
635
+ class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
636
+ Interpreter &Interp;
637
+ ASTContext &Ctx;
638
+ Sema &S;
639
+
640
+ public:
641
+ InProcessRuntimeInterfaceBuilder (Interpreter &Interp, ASTContext &C, Sema &S)
642
+ : Interp(Interp), Ctx(C), S(S) {}
643
+
644
+ TransformExprFunction *getPrintValueTransformer () override {
645
+ return &transformForValuePrinting;
646
+ }
647
+
648
+ private:
649
+ static ExprResult transformForValuePrinting (RuntimeInterfaceBuilder *Builder,
650
+ Expr *E,
651
+ ArrayRef<Expr *> FixedArgs) {
652
+ auto *B = static_cast <InProcessRuntimeInterfaceBuilder *>(Builder);
653
+
654
+ // Get rid of ExprWithCleanups.
655
+ if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
656
+ E = EWC->getSubExpr ();
657
+
658
+ InterfaceKindVisitor Visitor (B->Ctx , B->S , E);
659
+
660
+ // The Interpreter* parameter and the out parameter `OutVal`.
661
+ for (Expr *E : FixedArgs)
662
+ Visitor.Args .push_back (E);
663
+
664
+ QualType Ty = E->getType ();
665
+ QualType DesugaredTy = Ty.getDesugaredType (B->Ctx );
666
+
667
+ // For lvalue struct, we treat it as a reference.
668
+ if (DesugaredTy->isRecordType () && E->isLValue ()) {
669
+ DesugaredTy = B->Ctx .getLValueReferenceType (DesugaredTy);
670
+ Ty = B->Ctx .getLValueReferenceType (Ty);
671
+ }
672
+
673
+ Expr *TypeArg = CStyleCastPtrExpr (B->S , B->Ctx .VoidPtrTy ,
674
+ (uintptr_t )Ty.getAsOpaquePtr ());
675
+ // The QualType parameter `OpaqueType`, represented as `void*`.
676
+ Visitor.Args .push_back (TypeArg);
677
+
678
+ // We push the last parameter based on the type of the Expr. Note we need
679
+ // special care for rvalue struct.
680
+ Interpreter::InterfaceKind Kind = Visitor.Visit (&*DesugaredTy);
681
+ switch (Kind) {
682
+ case Interpreter::InterfaceKind::WithAlloc:
683
+ case Interpreter::InterfaceKind::CopyArray: {
684
+ // __clang_Interpreter_SetValueWithAlloc.
685
+ ExprResult AllocCall = B->S .ActOnCallExpr (
686
+ /* Scope=*/ nullptr ,
687
+ B->Interp
688
+ .getValuePrintingInfo ()[Interpreter::InterfaceKind::WithAlloc],
689
+ E->getBeginLoc (), Visitor.Args , E->getEndLoc ());
690
+ assert (!AllocCall.isInvalid () && " Can't create runtime interface call!" );
691
+
692
+ TypeSourceInfo *TSI =
693
+ B->Ctx .getTrivialTypeSourceInfo (Ty, SourceLocation ());
694
+
695
+ // Force CodeGen to emit destructor.
696
+ if (auto *RD = Ty->getAsCXXRecordDecl ()) {
697
+ auto *Dtor = B->S .LookupDestructor (RD);
698
+ Dtor->addAttr (UsedAttr::CreateImplicit (B->Ctx ));
699
+ B->Interp .getCompilerInstance ()->getASTConsumer ().HandleTopLevelDecl (
700
+ DeclGroupRef (Dtor));
701
+ }
702
+
703
+ // __clang_Interpreter_SetValueCopyArr.
704
+ if (Kind == Interpreter::InterfaceKind::CopyArray) {
705
+ const auto *ConstantArrTy =
706
+ cast<ConstantArrayType>(DesugaredTy.getTypePtr ());
707
+ size_t ArrSize = B->Ctx .getConstantArrayElementCount (ConstantArrTy);
708
+ Expr *ArrSizeExpr = IntegerLiteralExpr (B->Ctx , ArrSize);
709
+ Expr *Args[] = {E, AllocCall.get (), ArrSizeExpr};
710
+ return B->S .ActOnCallExpr (
711
+ /* Scope *=*/ nullptr ,
712
+ B->Interp
713
+ .getValuePrintingInfo ()[Interpreter::InterfaceKind::CopyArray],
714
+ SourceLocation (), Args, SourceLocation ());
715
+ }
716
+ Expr *Args[] = {
717
+ AllocCall.get (),
718
+ B->Interp .getValuePrintingInfo ()[Interpreter::InterfaceKind::NewTag]};
719
+ ExprResult CXXNewCall = B->S .BuildCXXNew (
720
+ E->getSourceRange (),
721
+ /* UseGlobal=*/ true , /* PlacementLParen=*/ SourceLocation (), Args,
722
+ /* PlacementRParen=*/ SourceLocation (),
723
+ /* TypeIdParens=*/ SourceRange (), TSI->getType (), TSI, std::nullopt,
724
+ E->getSourceRange (), E);
725
+
726
+ assert (!CXXNewCall.isInvalid () &&
727
+ " Can't create runtime placement new call!" );
728
+
729
+ return B->S .ActOnFinishFullExpr (CXXNewCall.get (),
730
+ /* DiscardedValue=*/ false );
731
+ }
732
+ // __clang_Interpreter_SetValueNoAlloc.
733
+ case Interpreter::InterfaceKind::NoAlloc: {
734
+ return B->S .ActOnCallExpr (
735
+ /* Scope=*/ nullptr ,
736
+ B->Interp .getValuePrintingInfo ()[Interpreter::InterfaceKind::NoAlloc],
737
+ E->getBeginLoc (), Visitor.Args , E->getEndLoc ());
738
+ }
739
+ default :
740
+ llvm_unreachable (" Unhandled Interpreter::InterfaceKind" );
741
+ }
742
+ }
743
+ };
716
744
} // namespace
717
745
746
+ static std::unique_ptr<RuntimeInterfaceBuilder>
747
+ createInProcessRuntimeInterfaceBuilder (Interpreter &Interp, ASTContext &Ctx,
748
+ Sema &S) {
749
+ return std::make_unique<InProcessRuntimeInterfaceBuilder>(Interp, Ctx, S);
750
+ }
751
+
718
752
// This synthesizes a call expression to a speciall
719
753
// function that is responsible for generating the Value.
720
754
// In general, we transform:
@@ -733,8 +767,13 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) {
733
767
Sema &S = getCompilerInstance ()->getSema ();
734
768
ASTContext &Ctx = S.getASTContext ();
735
769
736
- if (!FindRuntimeInterface ())
737
- llvm_unreachable (" We can't find the runtime iterface for pretty print!" );
770
+ if (!RuntimeIB) {
771
+ RuntimeIB = FindRuntimeInterface ();
772
+ AddPrintValueCall = RuntimeIB->getPrintValueTransformer ();
773
+ }
774
+
775
+ assert (AddPrintValueCall &&
776
+ " We don't have a runtime interface for pretty print!" );
738
777
739
778
// Create parameter `ThisInterp`.
740
779
auto *ThisInterp = CStyleCastPtrExpr (S, Ctx.VoidPtrTy , (uintptr_t )this );
@@ -743,9 +782,9 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) {
743
782
auto *OutValue = CStyleCastPtrExpr (S, Ctx.VoidPtrTy , (uintptr_t )&LastValue);
744
783
745
784
// Build `__clang_Interpreter_SetValue*` call.
746
- RuntimeInterfaceBuilder Builder (*this , Ctx, S, E, {ThisInterp, OutValue});
785
+ ExprResult Result =
786
+ AddPrintValueCall (RuntimeIB.get (), E, {ThisInterp, OutValue});
747
787
748
- ExprResult Result = Builder.getCall ();
749
788
// It could fail, like printing an array type in C. (not supported)
750
789
if (Result.isInvalid ())
751
790
return E;
0 commit comments