diff options
author | Jennifer Yu <jennifer.yu@intel.com> | 2019-05-30 01:05:46 +0000 |
---|---|---|
committer | Jennifer Yu <jennifer.yu@intel.com> | 2019-05-30 01:05:46 +0000 |
commit | 954ec09aed4f2be04bb5f4e10dbb4ea8bd19ef9a (patch) | |
tree | 23479cbe88acf8d056fb2e8d5c44a9978290c5fb /clang/lib/Analysis/CFG.cpp | |
parent | 192dd7df2f3104274db57e3b853390faa7e1aa25 (diff) | |
download | bcm5719-llvm-954ec09aed4f2be04bb5f4e10dbb4ea8bd19ef9a.tar.gz bcm5719-llvm-954ec09aed4f2be04bb5f4e10dbb4ea8bd19ef9a.zip |
clang support gnu asm goto.
Syntax:
asm [volatile] goto ( AssemblerTemplate
:
: InputOperands
: Clobbers
: GotoLabels)
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
New llvm IR is "callbr" for inline asm goto instead "call" for inline asm
For:
asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop);
IR:
callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,X,X,~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* blockaddress(@foo, %label_true), i8* blockaddress(@foo, %loop)) #1
to label %asm.fallthrough [label %label_true, label %loop], !srcloc !3
asm.fallthrough:
Compiler need to generate:
1> a dummy constarint 'X' for each label.
2> an unique fallthrough label for each asm goto stmt " asm.fallthrough%number".
Diagnostic
1> duplicate asm operand name are used in output, input and label.
2> goto out of scope.
llvm-svn: 362045
Diffstat (limited to 'clang/lib/Analysis/CFG.cpp')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 1d833593415..b53bfcca37c 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -549,6 +549,7 @@ private: CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); CFGBlock *VisitForStmt(ForStmt *F); CFGBlock *VisitGotoStmt(GotoStmt *G); + CFGBlock *VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc); CFGBlock *VisitIfStmt(IfStmt *I); CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); CFGBlock *VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc); @@ -1478,22 +1479,38 @@ std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { E = BackpatchBlocks.end(); I != E; ++I ) { CFGBlock *B = I->block; - const GotoStmt *G = cast<GotoStmt>(B->getTerminator()); - LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); - - // If there is no target for the goto, then we are looking at an - // incomplete AST. Handle this by not registering a successor. - if (LI == LabelMap.end()) continue; - - JumpTarget JT = LI->second; - prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition, - JT.scopePosition); - prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, - JT.scopePosition); - const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator( - B, I->scopePosition, JT.scopePosition); - appendScopeBegin(JT.block, VD, G); - addSuccessor(B, JT.block); + if (auto *G = dyn_cast<GotoStmt>(B->getTerminator())) { + LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); + // If there is no target for the goto, then we are looking at an + // incomplete AST. Handle this by not registering a successor. + if (LI == LabelMap.end()) + continue; + JumpTarget JT = LI->second; + prependAutomaticObjLifetimeWithTerminator(B, I->scopePosition, + JT.scopePosition); + prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, + JT.scopePosition); + const VarDecl *VD = prependAutomaticObjScopeEndWithTerminator( + B, I->scopePosition, JT.scopePosition); + appendScopeBegin(JT.block, VD, G); + addSuccessor(B, JT.block); + }; + if (auto *G = dyn_cast<GCCAsmStmt>(B->getTerminator())) { + CFGBlock *Successor = (I+1)->block; + for (auto *L : G->labels()) { + LabelMapTy::iterator LI = LabelMap.find(L->getLabel()); + // If there is no target for the goto, then we are looking at an + // incomplete AST. Handle this by not registering a successor. + if (LI == LabelMap.end()) + continue; + JumpTarget JT = LI->second; + // Successor has been added, so skip it. + if (JT.block == Successor) + continue; + addSuccessor(B, JT.block); + } + I++; + } } // Add successors to the Indirect Goto Dispatch block (if we have one). @@ -2142,6 +2159,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::GotoStmtClass: return VisitGotoStmt(cast<GotoStmt>(S)); + case Stmt::GCCAsmStmtClass: + return VisitGCCAsmStmt(cast<GCCAsmStmt>(S), asc); + case Stmt::IfStmtClass: return VisitIfStmt(cast<IfStmt>(S)); @@ -3146,6 +3166,28 @@ CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { return Block; } +CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) { + // Goto is a control-flow statement. Thus we stop processing the current + // block and create a new one. + + if (!G->isAsmGoto()) + return VisitStmt(G, asc); + + if (Block) { + Succ = Block; + if (badCFG) + return nullptr; + } + Block = createBlock(); + Block->setTerminator(G); + // We will backpatch this block later for all the labels. + BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); + // Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is + // used to avoid adding "Succ" again. + BackpatchBlocks.push_back(JumpSource(Succ, ScopePos)); + return Block; +} + CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { CFGBlock *LoopSuccessor = nullptr; |