aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/UninitializedValues.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2020-02-24 18:32:50 -0800
committerBill Wendling <isanbard@gmail.com>2020-02-24 18:51:29 -0800
commit50cac248773c3a023e8f6ceb9938bdd5e9f15da2 (patch)
treea215f4ce96662fe1c6aff2d13b23f2ba2f74c8c6 /clang/lib/Analysis/UninitializedValues.cpp
parent23c2a5ce33f0f05e4cc43c2cbb9009e9b549839c (diff)
downloadllvm-50cac248773c3a023e8f6ceb9938bdd5e9f15da2.zip
llvm-50cac248773c3a023e8f6ceb9938bdd5e9f15da2.tar.gz
llvm-50cac248773c3a023e8f6ceb9938bdd5e9f15da2.tar.bz2
Support output constraints on "asm goto"
Summary: Clang's "asm goto" feature didn't initially support outputs constraints. That was the same behavior as gcc's implementation. The decision by gcc not to support outputs was based on a restriction in their IR regarding terminators. LLVM doesn't restrict terminators from returning values (e.g. 'invoke'), so it made sense to support this feature. Output values are valid only on the 'fallthrough' path. If an output value's used on an indirect branch, then it's 'poisoned'. In theory, outputs *could* be valid on the 'indirect' paths, but it's very difficult to guarantee that the original semantics would be retained. E.g. because indirect labels could be used as data, we wouldn't be able to split critical edges in situations where two 'callbr' instructions have the same indirect label, because the indirect branch's destination would no longer be the same. Reviewers: jyknight, nickdesaulniers, hfinkel Reviewed By: jyknight, nickdesaulniers Subscribers: MaskRay, rsmith, hiraditya, llvm-commits, cfe-commits, craig.topper, rnk Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D69876
Diffstat (limited to 'clang/lib/Analysis/UninitializedValues.cpp')
-rw-r--r--clang/lib/Analysis/UninitializedValues.cpp15
1 files changed, 15 insertions, 0 deletions
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index ff14e18..a4a900c 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -475,6 +475,7 @@ public:
void VisitCallExpr(CallExpr *ce);
void VisitDeclRefExpr(DeclRefExpr *dr);
void VisitDeclStmt(DeclStmt *ds);
+ void VisitGCCAsmStmt(GCCAsmStmt *as);
void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS);
void VisitObjCMessageExpr(ObjCMessageExpr *ME);
void VisitOMPExecutableDirective(OMPExecutableDirective *ED);
@@ -760,6 +761,16 @@ void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
}
}
+void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) {
+ // An "asm goto" statement is a terminator that may initialize some variables.
+ if (!as->isAsmGoto())
+ return;
+
+ for (const auto &o : as->outputs())
+ if (const VarDecl *VD = findVar(o).getDecl())
+ vals[VD] = Initialized;
+}
+
void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) {
// If the Objective-C message expression is an implicit no-return that
// is not modeled in the CFG, set the tracked dataflow values to Unknown.
@@ -797,6 +808,10 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
if (Optional<CFGStmt> cs = I.getAs<CFGStmt>())
tf.Visit(const_cast<Stmt *>(cs->getStmt()));
}
+ CFGTerminator terminator = block->getTerminator();
+ if (GCCAsmStmt *as = dyn_cast_or_null<GCCAsmStmt>(terminator.getStmt()))
+ if (as->isAsmGoto())
+ tf.Visit(as);
return vals.updateValueVectorWithScratch(block);
}