zoukankan      html  css  js  c++  java
  • Clang AST到IR的转换

    边介绍了几节Clang AST,包括AST的读取,Rewriter,AST的插入等,这里想从AST到IR的转换,介绍一点Clang源码的内容。

    前边已经提到了想打印AST树内容的话,需要使用clang -fsyntax-only -Xclang -ast-dump 命令来进行。对于llvm各种文件格式的转换,有一个图说的比较清楚,内容来源见水印。

     我们使用的源码还是以上次使用的view.cpp

     1 int foo(int a, int b, int *c) {
     2     int ret = 0;
     3     if (a > b) {
     4         ret = a;
     5     } else {
     6         ret = b;
     7     }
     8     for (int temp = 0; temp < 100; ++temp) {
     9         *c = (*c + temp);
    10     }
    11     return ret;
    12 }
    13 
    14 
    15 int main() {
    16     int a = 1, b = 2;
    17     int c = 0;
    18     int d = foo(a, b, &c);
    19     return 0;
    20 }
    View Code

    打印出来的view.ll文件如下:

    ; ModuleID = 'view.cpp'
    source_filename = "view.cpp"
    target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
    target triple = "x86_64-unknown-linux-gnu"
    
    ; Function Attrs: noinline nounwind optnone uwtable mustprogress
    define dso_local i32 @_Z3fooiiPi(i32 %0, i32 %1, i32* %2) #0 {
      %4 = alloca i32, align 4
      %5 = alloca i32, align 4
      %6 = alloca i32*, align 8
      %7 = alloca i32, align 4
      %8 = alloca i32, align 4
      store i32 %0, i32* %4, align 4
      store i32 %1, i32* %5, align 4
      store i32* %2, i32** %6, align 8
      store i32 0, i32* %7, align 4
      %9 = load i32, i32* %4, align 4
      %10 = load i32, i32* %5, align 4
      %11 = icmp sgt i32 %9, %10
      br i1 %11, label %12, label %14
    
    12:                                               ; preds = %3
      %13 = load i32, i32* %4, align 4
      store i32 %13, i32* %7, align 4
      br label %16
    
    14:                                               ; preds = %3
      %15 = load i32, i32* %5, align 4
      store i32 %15, i32* %7, align 4
      br label %16
    
    16:                                               ; preds = %14, %12
      store i32 0, i32* %8, align 4
      br label %17
    
    17:                                               ; preds = %26, %16
      %18 = load i32, i32* %8, align 4
      %19 = icmp slt i32 %18, 100
      br i1 %19, label %20, label %29
    
    20:                                               ; preds = %17
      %21 = load i32*, i32** %6, align 8
      %22 = load i32, i32* %21, align 4
      %23 = load i32, i32* %8, align 4
      %24 = add nsw i32 %22, %23
      %25 = load i32*, i32** %6, align 8
      store i32 %24, i32* %25, align 4
      br label %26
    
    26:                                               ; preds = %20
      %27 = load i32, i32* %8, align 4
      %28 = add nsw i32 %27, 1
      store i32 %28, i32* %8, align 4
      br label %17, !llvm.loop !2
    
    29:                                               ; preds = %17
      %30 = load i32, i32* %7, align 4
      ret i32 %30
    }
    
    ; Function Attrs: noinline norecurse nounwind optnone uwtable mustprogress
    define dso_local i32 @main() #1 {
      %1 = alloca i32, align 4
      %2 = alloca i32, align 4
      %3 = alloca i32, align 4
      %4 = alloca i32, align 4
      %5 = alloca i32, align 4
      store i32 0, i32* %1, align 4
      store i32 1, i32* %2, align 4
      store i32 2, i32* %3, align 4
      store i32 0, i32* %4, align 4
      %6 = load i32, i32* %2, align 4
      %7 = load i32, i32* %3, align 4
      %8 = call i32 @_Z3fooiiPi(i32 %6, i32 %7, i32* %4)
      store i32 %8, i32* %5, align 4
      ret i32 0
    }
    
    ; Function Attrs: noinline norecurse nounwind optnone uwtable mustprogress
    define dso_local i32 @main() #1 {
      %1 = alloca i32, align 4
      %2 = alloca i32, align 4
      %3 = alloca i32, align 4
      %4 = alloca i32, align 4
      %5 = alloca i32, align 4
      store i32 0, i32* %1, align 4
      store i32 1, i32* %2, align 4
      store i32 2, i32* %3, align 4
      store i32 0, i32* %4, align 4
      %6 = load i32, i32* %2, align 4
      %7 = load i32, i32* %3, align 4
      %8 = call i32 @_Z3fooiiPi(i32 %6, i32 %7, i32* %4)
      store i32 %8, i32* %5, align 4
      ret i32 0
    }
    
    attributes #0 = { noinline nounwind optnone uwtable mustprogress "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
    attributes #1 = { noinline norecurse nounwind optnone uwtable mustprogress "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
    
    !llvm.module.flags = !{!0}
    !llvm.ident = !{!1}
    
    !0 = !{i32 1, !"wchar_size", i32 4}
    !1 = !{!"clang version 13.0.0"}
    !2 = distinct !{!2, !3}
    !3 = !{!"llvm.loop.mustprogress"}
    

      对于如何生成llvm的IR(其实是以bc文件格式存在,这里为了human read),主要通过namespace clang::CodeGen来记性,在llvm/lib/CodeGen目录下有很多以CG开头的文件,负责各种类型的AST节点的CodeGen工作,这里我仅以ForStmt这个节点来进行介绍。

           从Clang 的Doxgen图上来看,ForStmt继承至Stmt(https://clang.llvm.org/doxygen/classclang_1_1ForStmt.html)

    很多AST节点类型都继承至Stmt,因此,不看代码,从设计的调度来看,应该是一个switch case的结构,通过判断节点的类型来分别进入到每个AST节点进行CodeGen。

    定位到clang/lib/CodeGen/CGStmt.cpp中,第二个函数就看到了

    void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs)
    从名字上就是“EmitStmt”,指令Emit,StmtEmit,这可以理解为一条线。我了解的阅读代码有两条线,一条是使用gdb一步步下断点,不停的跟进去,这是非常正确的,也是大家一般推荐的,但是在工程量非常大的project上可能不实用,主要是main函数进来到你真正想看的地方有点太过漫长,比较耗时耗力,还有一条路线是直接读代码,也就是所谓的猜,一般开源的,有一定影响力的代码,设计上都比较清晰,靠注释和函数名可以解决很多问题,前提是需要你对该领域有一定了解,对初学者来说难度巨大。一般来说,两条线是交替进行的,gdb加直接读,容易事半功倍,同时,可以考虑在源码上加一些输出(printf大法),来判断函数调用过程。
    这里我将整个EmitStmt代码贴一下:
      1 void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
      2   assert(S && "Null statement?");
      3   llvm::errs()<<"EmitStmt
    ";
      4   PGO.setCurrentStmt(S);
      5 
      6   // These statements have their own debug info handling.
      7   if (EmitSimpleStmt(S, Attrs))
      8     return;
      9 
     10   // Check if we are generating unreachable code.
     11   if (!HaveInsertPoint()) {
     12     // If so, and the statement doesn't contain a label, then we do not need to
     13     // generate actual code. This is safe because (1) the current point is
     14     // unreachable, so we don't need to execute the code, and (2) we've already
     15     // handled the statements which update internal data structures (like the
     16     // local variable map) which could be used by subsequent statements.
     17     if (!ContainsLabel(S)) {
     18       // Verify that any decl statements were handled as simple, they may be in
     19       // scope of subsequent reachable statements.
     20       assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!");
     21       return;
     22     }
     23 
     24     // Otherwise, make a new block to hold the code.
     25     EnsureInsertPoint();
     26   }
     27 llvm::errs()<<"EmitStmt Emit
    ";
     28   // Generate a stoppoint if we are emitting debug info.
     29   EmitStopPoint(S);
     30 
     31   // Ignore all OpenMP directives except for simd if OpenMP with Simd is
     32   // enabled.
     33   if (getLangOpts().OpenMP && getLangOpts().OpenMPSimd) {
     34     if (const auto *D = dyn_cast<OMPExecutableDirective>(S)) {
     35       EmitSimpleOMPExecutableDirective(*D);
     36       return;
     37     }
     38   }
     39 
     40   switch (S->getStmtClass()) {
     41   case Stmt::NoStmtClass:
     42   case Stmt::CXXCatchStmtClass:
     43   case Stmt::SEHExceptStmtClass:
     44   case Stmt::SEHFinallyStmtClass:
     45   case Stmt::MSDependentExistsStmtClass:
     46     llvm_unreachable("invalid statement class to emit generically");
     47   case Stmt::NullStmtClass:
     48   case Stmt::CompoundStmtClass:
     49   case Stmt::DeclStmtClass:
     50   case Stmt::LabelStmtClass:
     51   case Stmt::AttributedStmtClass:
     52   case Stmt::GotoStmtClass:
     53   case Stmt::BreakStmtClass:
     54   case Stmt::ContinueStmtClass:
     55   case Stmt::DefaultStmtClass:
     56   case Stmt::CaseStmtClass:
     57   case Stmt::SEHLeaveStmtClass:
     58     llvm_unreachable("should have emitted these statements as simple");
     59 
     60 #define STMT(Type, Base)
     61 #define ABSTRACT_STMT(Op)
     62 #define EXPR(Type, Base) 
     63   case Stmt::Type##Class:
     64 #include "clang/AST/StmtNodes.inc"
     65   {
     66     // Remember the block we came in on.
     67     llvm::BasicBlock *incoming = Builder.GetInsertBlock();
     68     assert(incoming && "expression emission must have an insertion point");
     69 
     70     EmitIgnoredExpr(cast<Expr>(S));
     71 
     72     llvm::BasicBlock *outgoing = Builder.GetInsertBlock();
     73     assert(outgoing && "expression emission cleared block!");
     74 
     75     // The expression emitters assume (reasonably!) that the insertion
     76     // point is always set.  To maintain that, the call-emission code
     77     // for noreturn functions has to enter a new block with no
     78     // predecessors.  We want to kill that block and mark the current
     79     // insertion point unreachable in the common case of a call like
     80     // "exit();".  Since expression emission doesn't otherwise create
     81     // blocks with no predecessors, we can just test for that.
     82     // However, we must be careful not to do this to our incoming
     83     // block, because *statement* emission does sometimes create
     84     // reachable blocks which will have no predecessors until later in
     85     // the function.  This occurs with, e.g., labels that are not
     86     // reachable by fallthrough.
     87     if (incoming != outgoing && outgoing->use_empty()) {
     88       outgoing->eraseFromParent();
     89       Builder.ClearInsertionPoint();
     90     }
     91     break;
     92   }
     93 
     94   case Stmt::IndirectGotoStmtClass:
     95     EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
     96 
     97   case Stmt::IfStmtClass:      EmitIfStmt(cast<IfStmt>(*S));              break;
     98   case Stmt::WhileStmtClass:   EmitWhileStmt(cast<WhileStmt>(*S), Attrs); break;
     99   case Stmt::DoStmtClass:      EmitDoStmt(cast<DoStmt>(*S), Attrs);       break;
    100   case Stmt::ForStmtClass:    llvm::errs()<<"EmitForStmt
    "; EmitForStmt(cast<ForStmt>(*S), Attrs);     break;
    101 
    102   case Stmt::ReturnStmtClass:  EmitReturnStmt(cast<ReturnStmt>(*S));      break;
    103 
    104   case Stmt::SwitchStmtClass:  EmitSwitchStmt(cast<SwitchStmt>(*S));      break;
    105   case Stmt::GCCAsmStmtClass:  // Intentional fall-through.
    106   case Stmt::MSAsmStmtClass:   EmitAsmStmt(cast<AsmStmt>(*S));            break;
    107   case Stmt::CoroutineBodyStmtClass:
    108     EmitCoroutineBody(cast<CoroutineBodyStmt>(*S));
    109     break;
    110   case Stmt::CoreturnStmtClass:
    111     EmitCoreturnStmt(cast<CoreturnStmt>(*S));
    112     break;
    113   case Stmt::CapturedStmtClass: {
    114     const CapturedStmt *CS = cast<CapturedStmt>(S);
    115     EmitCapturedStmt(*CS, CS->getCapturedRegionKind());
    116     }
    117     break;
    118   case Stmt::ObjCAtTryStmtClass:
    119     EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
    120     break;
    121   case Stmt::ObjCAtCatchStmtClass:
    122     llvm_unreachable(
    123                     "@catch statements should be handled by EmitObjCAtTryStmt");
    124   case Stmt::ObjCAtFinallyStmtClass:
    125     llvm_unreachable(
    126                   "@finally statements should be handled by EmitObjCAtTryStmt");
    127   case Stmt::ObjCAtThrowStmtClass:
    128     EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S));
    129     break;
    130   case Stmt::ObjCAtSynchronizedStmtClass:
    131     EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S));
    132     break;
    133   case Stmt::ObjCForCollectionStmtClass:
    134     EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S));
    135     break;
    136   case Stmt::ObjCAutoreleasePoolStmtClass:
    137     EmitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(*S));
    138     break;
    139 
    140   case Stmt::CXXTryStmtClass:
    141     EmitCXXTryStmt(cast<CXXTryStmt>(*S));
    142     break;
    143   case Stmt::CXXForRangeStmtClass:
    144     EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S), Attrs);
    145     break;
    146   case Stmt::SEHTryStmtClass:
    147     EmitSEHTryStmt(cast<SEHTryStmt>(*S));
    148     break;
    149   case Stmt::OMPCanonicalLoopClass:
    150     EmitOMPCanonicalLoop(cast<OMPCanonicalLoop>(S));
    151     break;
    152   case Stmt::OMPParallelDirectiveClass:
    153     EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
    154     break;
    155   case Stmt::OMPSimdDirectiveClass:
    156     EmitOMPSimdDirective(cast<OMPSimdDirective>(*S));
    157     break;
    158   case Stmt::OMPTileDirectiveClass:
    159     EmitOMPTileDirective(cast<OMPTileDirective>(*S));
    160     break;
    161   case Stmt::OMPForDirectiveClass:
    162     EmitOMPForDirective(cast<OMPForDirective>(*S));
    163     break;
    164   case Stmt::OMPForSimdDirectiveClass:
    165     EmitOMPForSimdDirective(cast<OMPForSimdDirective>(*S));
    166     break;
    167   case Stmt::OMPSectionsDirectiveClass:
    168     EmitOMPSectionsDirective(cast<OMPSectionsDirective>(*S));
    169     break;
    170   case Stmt::OMPSectionDirectiveClass:
    171     EmitOMPSectionDirective(cast<OMPSectionDirective>(*S));
    172     break;
    173   case Stmt::OMPSingleDirectiveClass:
    174     EmitOMPSingleDirective(cast<OMPSingleDirective>(*S));
    175     break;
    176   case Stmt::OMPMasterDirectiveClass:
    177     EmitOMPMasterDirective(cast<OMPMasterDirective>(*S));
    178     break;
    179   case Stmt::OMPCriticalDirectiveClass:
    180     EmitOMPCriticalDirective(cast<OMPCriticalDirective>(*S));
    181     break;
    182   case Stmt::OMPParallelForDirectiveClass:
    183     EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S));
    184     break;
    185   case Stmt::OMPParallelForSimdDirectiveClass:
    186     EmitOMPParallelForSimdDirective(cast<OMPParallelForSimdDirective>(*S));
    187     break;
    188   case Stmt::OMPParallelMasterDirectiveClass:
    189     EmitOMPParallelMasterDirective(cast<OMPParallelMasterDirective>(*S));
    190     break;
    191   case Stmt::OMPParallelSectionsDirectiveClass:
    192     EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S));
    193     break;
    194   case Stmt::OMPTaskDirectiveClass:
    195     EmitOMPTaskDirective(cast<OMPTaskDirective>(*S));
    196     break;
    197   case Stmt::OMPTaskyieldDirectiveClass:
    198     EmitOMPTaskyieldDirective(cast<OMPTaskyieldDirective>(*S));
    199     break;
    200   case Stmt::OMPBarrierDirectiveClass:
    201     EmitOMPBarrierDirective(cast<OMPBarrierDirective>(*S));
    202     break;
    203   case Stmt::OMPTaskwaitDirectiveClass:
    204     EmitOMPTaskwaitDirective(cast<OMPTaskwaitDirective>(*S));
    205     break;
    206   case Stmt::OMPTaskgroupDirectiveClass:
    207     EmitOMPTaskgroupDirective(cast<OMPTaskgroupDirective>(*S));
    208     break;
    209   case Stmt::OMPFlushDirectiveClass:
    210     EmitOMPFlushDirective(cast<OMPFlushDirective>(*S));
    211     break;
    212   case Stmt::OMPDepobjDirectiveClass:
    213     EmitOMPDepobjDirective(cast<OMPDepobjDirective>(*S));
    214     break;
    215   case Stmt::OMPScanDirectiveClass:
    216     EmitOMPScanDirective(cast<OMPScanDirective>(*S));
    217     break;
    218   case Stmt::OMPOrderedDirectiveClass:
    219     EmitOMPOrderedDirective(cast<OMPOrderedDirective>(*S));
    220     break;
    221   case Stmt::OMPAtomicDirectiveClass:
    222     EmitOMPAtomicDirective(cast<OMPAtomicDirective>(*S));
    223     break;
    224   case Stmt::OMPTargetDirectiveClass:
    225     EmitOMPTargetDirective(cast<OMPTargetDirective>(*S));
    226     break;
    227   case Stmt::OMPTeamsDirectiveClass:
    228     EmitOMPTeamsDirective(cast<OMPTeamsDirective>(*S));
    229     break;
    230   case Stmt::OMPCancellationPointDirectiveClass:
    231     EmitOMPCancellationPointDirective(cast<OMPCancellationPointDirective>(*S));
    232     break;
    233   case Stmt::OMPCancelDirectiveClass:
    234     EmitOMPCancelDirective(cast<OMPCancelDirective>(*S));
    235     break;
    236   case Stmt::OMPTargetDataDirectiveClass:
    237     EmitOMPTargetDataDirective(cast<OMPTargetDataDirective>(*S));
    238     break;
    239   case Stmt::OMPTargetEnterDataDirectiveClass:
    240     EmitOMPTargetEnterDataDirective(cast<OMPTargetEnterDataDirective>(*S));
    241     break;
    242   case Stmt::OMPTargetExitDataDirectiveClass:
    243     EmitOMPTargetExitDataDirective(cast<OMPTargetExitDataDirective>(*S));
    244     break;
    245   case Stmt::OMPTargetParallelDirectiveClass:
    246     EmitOMPTargetParallelDirective(cast<OMPTargetParallelDirective>(*S));
    247     break;
    248   case Stmt::OMPTargetParallelForDirectiveClass:
    249     EmitOMPTargetParallelForDirective(cast<OMPTargetParallelForDirective>(*S));
    250     break;
    251   case Stmt::OMPTaskLoopDirectiveClass:
    252     EmitOMPTaskLoopDirective(cast<OMPTaskLoopDirective>(*S));
    253     break;
    254   case Stmt::OMPTaskLoopSimdDirectiveClass:
    255     EmitOMPTaskLoopSimdDirective(cast<OMPTaskLoopSimdDirective>(*S));
    256     break;
    257   case Stmt::OMPMasterTaskLoopDirectiveClass:
    258     EmitOMPMasterTaskLoopDirective(cast<OMPMasterTaskLoopDirective>(*S));
    259     break;
    260   case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
    261     EmitOMPMasterTaskLoopSimdDirective(
    262         cast<OMPMasterTaskLoopSimdDirective>(*S));
    263     break;
    264   case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
    265     EmitOMPParallelMasterTaskLoopDirective(
    266         cast<OMPParallelMasterTaskLoopDirective>(*S));
    267     break;
    268   case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
    269     EmitOMPParallelMasterTaskLoopSimdDirective(
    270         cast<OMPParallelMasterTaskLoopSimdDirective>(*S));
    271     break;
    272   case Stmt::OMPDistributeDirectiveClass:
    273     EmitOMPDistributeDirective(cast<OMPDistributeDirective>(*S));
    274     break;
    275   case Stmt::OMPTargetUpdateDirectiveClass:
    276     EmitOMPTargetUpdateDirective(cast<OMPTargetUpdateDirective>(*S));
    277     break;
    278   case Stmt::OMPDistributeParallelForDirectiveClass:
    279     EmitOMPDistributeParallelForDirective(
    280         cast<OMPDistributeParallelForDirective>(*S));
    281     break;
    282   case Stmt::OMPDistributeParallelForSimdDirectiveClass:
    283     EmitOMPDistributeParallelForSimdDirective(
    284         cast<OMPDistributeParallelForSimdDirective>(*S));
    285     break;
    286   case Stmt::OMPDistributeSimdDirectiveClass:
    287     EmitOMPDistributeSimdDirective(cast<OMPDistributeSimdDirective>(*S));
    288     break;
    289   case Stmt::OMPTargetParallelForSimdDirectiveClass:
    290     EmitOMPTargetParallelForSimdDirective(
    291         cast<OMPTargetParallelForSimdDirective>(*S));
    292     break;
    293   case Stmt::OMPTargetSimdDirectiveClass:
    294     EmitOMPTargetSimdDirective(cast<OMPTargetSimdDirective>(*S));
    295     break;
    296   case Stmt::OMPTeamsDistributeDirectiveClass:
    297     EmitOMPTeamsDistributeDirective(cast<OMPTeamsDistributeDirective>(*S));
    298     break;
    299   case Stmt::OMPTeamsDistributeSimdDirectiveClass:
    300     EmitOMPTeamsDistributeSimdDirective(
    301         cast<OMPTeamsDistributeSimdDirective>(*S));
    302     break;
    303   case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
    304     EmitOMPTeamsDistributeParallelForSimdDirective(
    305         cast<OMPTeamsDistributeParallelForSimdDirective>(*S));
    306     break;
    307   case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
    308     EmitOMPTeamsDistributeParallelForDirective(
    309         cast<OMPTeamsDistributeParallelForDirective>(*S));
    310     break;
    311   case Stmt::OMPTargetTeamsDirectiveClass:
    312     EmitOMPTargetTeamsDirective(cast<OMPTargetTeamsDirective>(*S));
    313     break;
    314   case Stmt::OMPTargetTeamsDistributeDirectiveClass:
    315     EmitOMPTargetTeamsDistributeDirective(
    316         cast<OMPTargetTeamsDistributeDirective>(*S));
    317     break;
    318   case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
    319     EmitOMPTargetTeamsDistributeParallelForDirective(
    320         cast<OMPTargetTeamsDistributeParallelForDirective>(*S));
    321     break;
    322   case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
    323     EmitOMPTargetTeamsDistributeParallelForSimdDirective(
    324         cast<OMPTargetTeamsDistributeParallelForSimdDirective>(*S));
    325     break;
    326   case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
    327     EmitOMPTargetTeamsDistributeSimdDirective(
    328         cast<OMPTargetTeamsDistributeSimdDirective>(*S));
    329     break;
    330   }
    331 }
    EmitStmt

    前边是一些判断,主要的结构和我们猜想的一样是一个大的switch case判断,根据S->getStmtClass()来进行,中间还搞进来一个大的宏include,

    #define STMT(Type, Base)
    #define ABSTRACT_STMT(Op)
    #define EXPR(Type, Base) 
      case Stmt::Type##Class:
    #include "clang/AST/StmtNodes.inc"
    

      这里是把所有的StmtNodes.inc都包进来。后边紧跟着就是case Stmt::ForStmtClass类型的判断。

    我们进入EmitForStmt(cast<ForStmt>(*S), Attrs);里边看一下

      1 void CodeGenFunction::EmitForStmt(const ForStmt &S,
      2                                   ArrayRef<const Attr *> ForAttrs) {
      3   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
      4 
      5   LexicalScope ForScope(*this, S.getSourceRange());
      6 
      7   // Evaluate the first part before the loop.
      8   if (S.getInit())
      9     EmitStmt(S.getInit());
     10 
     11   // Start the loop with a block that tests the condition.
     12   // If there's an increment, the continue scope will be overwritten
     13   // later.
     14   JumpDest Continue = getJumpDestInCurrentScope("for.cond");
     15   llvm::BasicBlock *CondBlock = Continue.getBlock();
     16   EmitBlock(CondBlock);
     17 
     18   bool LoopMustProgress = false;
     19   Expr::EvalResult Result;
     20   if (LanguageRequiresProgress()) {
     21     if (!S.getCond()) {
     22       FnIsMustProgress = false;
     23     } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) {
     24       LoopMustProgress = true;
     25     }
     26   }
     27 
     28   const SourceRange &R = S.getSourceRange();
     29   LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
     30                  SourceLocToDebugLoc(R.getBegin()),
     31                  SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
     32 
     33   // If the for loop doesn't have an increment we can just use the
     34   // condition as the continue block.  Otherwise we'll need to create
     35   // a block for it (in the current scope, i.e. in the scope of the
     36   // condition), and that we will become our continue block.
     37   if (S.getInc())
     38     Continue = getJumpDestInCurrentScope("for.inc");
     39 
     40   // Store the blocks to use for break and continue.
     41   BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
     42 
     43   // Create a cleanup scope for the condition variable cleanups.
     44   LexicalScope ConditionScope(*this, S.getSourceRange());
     45 
     46   if (S.getCond()) {
     47     // If the for statement has a condition scope, emit the local variable
     48     // declaration.
     49     if (S.getConditionVariable()) {
     50       EmitDecl(*S.getConditionVariable());
     51     }
     52 
     53     llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
     54     // If there are any cleanups between here and the loop-exit scope,
     55     // create a block to stage a loop exit along.
     56     if (ForScope.requiresCleanups())
     57       ExitBlock = createBasicBlock("for.cond.cleanup");
     58 
     59     // As long as the condition is true, iterate the loop.
     60     llvm::BasicBlock *ForBody = createBasicBlock("for.body");
     61 
     62     // C99 6.8.5p2/p4: The first substatement is executed if the expression
     63     // compares unequal to 0.  The condition must be a scalar type.
     64     llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
     65     llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
     66         S.getCond(), getProfileCount(S.getBody()), S.getBody());
     67 
     68     if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
     69       if (C->isOne())
     70         FnIsMustProgress = false;
     71 
     72     Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
     73 
     74     if (ExitBlock != LoopExit.getBlock()) {
     75       EmitBlock(ExitBlock);
     76       EmitBranchThroughCleanup(LoopExit);
     77     }
     78 
     79     EmitBlock(ForBody);
     80   } else {
     81     // Treat it as a non-zero constant.  Don't even create a new block for the
     82     // body, just fall into it.
     83   }
     84   incrementProfileCounter(&S);
     85 
     86   {
     87     // Create a separate cleanup scope for the body, in case it is not
     88     // a compound statement.
     89     RunCleanupsScope BodyScope(*this);
     90     EmitStmt(S.getBody());
     91   }
     92 
     93   // If there is an increment, emit it next.
     94   if (S.getInc()) {
     95     EmitBlock(Continue.getBlock());
     96     EmitStmt(S.getInc());
     97   }
     98 
     99   BreakContinueStack.pop_back();
    100 
    101   ConditionScope.ForceCleanup();
    102 
    103   EmitStopPoint(&S);
    104   EmitBranch(CondBlock);
    105 
    106   ForScope.ForceCleanup();
    107 
    108   LoopStack.pop();
    109 
    110   // Emit the fall-through block.
    111   EmitBlock(LoopExit.getBlock(), true);
    112 }

    大概流程和我之前处理ForStmt的读取的方式是一样的,getInit()/getCond()/getInc()/getBody()分别进行处理,每个生成对应Block,这里处理的时候,因为最后都需要处理成跳转的形式,需要预先记录下for结束的出口,然后按照Init() / Cond() /Body() / Inc() / Cond() 的顺序进行处理。

  • 相关阅读:
    Alpha冲刺(2/10)——2019.4.25
    Alpha冲刺(1/10)——2019.4.24
    Alpha冲刺——序言篇(任务与计划)
    团队作业第六次—团队Github实战训练
    团队第四次作业答辩——反思与总结
    团队作业第五次—项目系统设计与数据库设计
    项目Alpha冲刺--6/10
    项目Alpha冲刺--5/10
    项目Alpha冲刺--4/10
    项目Alpha冲刺--3/10
  • 原文地址:https://www.cnblogs.com/jourluohua/p/14532433.html
Copyright © 2011-2022 走看看