Skip to content

Commit

Permalink
Update the available facts analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
arbipher committed Aug 25, 2021
1 parent 2e5631a commit f1aa427
Show file tree
Hide file tree
Showing 8 changed files with 331 additions and 249 deletions.
10 changes: 10 additions & 0 deletions clang/include/clang/AST/ExprUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_EXPRUTILS_H
#define LLVM_CLANG_EXPRUTILS_H

#include "clang/AST/CanonBounds.h"
#include "clang/AST/Expr.h"
#include "clang/Sema/Sema.h"
#include <queue>
Expand Down Expand Up @@ -174,6 +175,15 @@ class ExprUtil {

// IsVarUsed searches whether V is used in E.
static bool IsVarUsed(Sema &S, VarDecl *V, Expr *E);

// Invoke IgnoreValuePreservingOperations to strip off casts.
// @param[in] E is the expression whose casts must be stripped.
// @return E with casts stripped off.
static Expr *IgnoreCasts(Lexicographic &Lex, ASTContext &Ctx, const Expr *E);

// Based on IgnoreCasts, strip off more casts including IntegralCast and
// LValueToRValue
static Expr *TranspareCasts(Lexicographic &Lex, ASTContext &Ctx, const Expr *E);
};

} // end namespace clang
Expand Down
107 changes: 51 additions & 56 deletions clang/include/clang/Sema/AvailableWhereFactsAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,13 @@
#ifndef LLVM_AVAILABLE_WHERE_FACTS_ANALYSIS_H
#define LLVM_AVAILABLE_WHERE_FACTS_ANALYSIS_H

#include "clang/AST/CanonBounds.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/AST/CanonBounds.h"
#include "clang/Sema/CheckedCAnalysesPrepass.h"
#include "clang/Sema/Sema.h"

namespace clang {

// StmtFactsMapTy denotes a map from a statement to the facts associated
// with it.
using StmtFactsMapTy = llvm::DenseMap<const Stmt *, AbstractFactListTy>;

// StmtSetTy denotes a set of statements.
using StmtSetTy = llvm::SmallPtrSet<const Stmt *, 16>;

Expand All @@ -36,10 +32,9 @@ namespace clang {
// for printing the blocks in a deterministic order.
using OrderedBlocksTy = std::vector<const CFGBlock *>;

// AvailableFactsKillKind denotes two kinds of kill variables.
// KillExpr denotes a variable to kill a EqualityOpFact or a InferredFact
// KillBounds denotes a variable to kill a BoundsDeclFact.
enum AvailableFactsKillKind {
// KillExpr denotes a variable that kills an EqualityOpFact or an InferredFact
// KillBounds denotes a variable that kills a BoundsDeclFact.
enum class AvailableFactsKillKind {
KillExpr,
KillBounds
};
Expand All @@ -49,9 +44,9 @@ namespace clang {
using KillVarSetTy = llvm::SmallSet<KillVar, 2>;
using StmtKillVarSetTy = llvm::DenseMap<const Stmt *, KillVarSetTy>;

// FactComparisionMapTy denotes the comparision result of two facts.
using FactComparision = std::pair<const AbstractFact *, const AbstractFact *>;
using FactComparisionMapTy = llvm::DenseMap<FactComparision, bool>;
// FactComparisonMapTy denotes the comparsion result of two facts.
using FactComparison = std::pair<const AbstractFact *, const AbstractFact *>;
using FactComparisonMapTy = llvm::DenseMap<FactComparison, bool>;

} // end namespace clang

Expand All @@ -71,30 +66,18 @@ namespace clang {
ASTContext &Ctx;
Lexicographic Lex;
llvm::raw_ostream &OS;
FactComparisionMapTy FactComparisionMap;
FactComparisonMapTy FactComparisonMap;

public:
AvailableFactsUtil(Sema &SemaRef, CFG *Cfg,
ASTContext &Ctx, Lexicographic Lex) :
SemaRef(SemaRef), Cfg(Cfg), Ctx(Ctx), Lex(Lex), OS(llvm::outs()),
FactComparisionMap(FactComparisionMapTy()) {}

// Pretty print a expr
void Print(const Expr *) const;

// Pretty print a Stmt
void Print(const Stmt *) const;

// Pretty print an abstract fact
void DumpAbstractFact(const AbstractFact *Fact) const;

// Pretty print a list of abstract facts
void DumpAbstractFacts(const AbstractFactListTy &Facts) const;
FactComparisonMap(FactComparisonMapTy()) {}

// Pretty print a set of variables.
void PrintKillVarSet(KillVarSetTy VarSet) const;

// Determine if the edge from PredBlock to CurrBlock is a fallthrough.
// Determine if the edge from PredBlock to CurrBlock is a fallthrough.
// @param[in] PredBlock is a predecessor block of the current block.
// @param[in] CurrBlock is the current block.
// @return Returns true if the edge is a fallthrough, false otherwise.
Expand All @@ -108,7 +91,7 @@ namespace clang {
bool IsSwitchCaseBlock(const CFGBlock *PredBlock,
const CFGBlock *CurrBlock) const;

// Determine the boolean state of an edge when the
// Determine the boolean state of an edge when the previous block is an if-condition
// @param[in] PredBlock is a predecessor block of the current block.
// @param[in] CurrBlock is the current block.
// @return Returns true if true if on the edge, false otherwise.
Expand All @@ -119,16 +102,7 @@ namespace clang {
// @param[in] CurrStmt is a given statement.
// @param[out] ModifiedVars is a set of variables modified by CurrStmt or
// statements nested in CurrStmt.
void GetModifiedVars(const Stmt *CurrStmt, VarSetTy &ModifiedVars) const;

// Invoke IgnoreValuePreservingOperations to strip off casts.
// @param[in] E is the expression whose casts must be stripped.
// @return E with casts stripped off.
Expr *IgnoreCasts(const Expr *E) const;

// Based on IgnoreCasts, strip off more casts including IntegralCast and
// LValueToRValue
Expr *TranspareCasts(const Expr *E) const;
void GetModifiedVars(const Stmt *CurrStmt, VarSetTy &ModifiedVars);

// We do not want to run dataflow analysis on null blocks or the exit
// block. So we skip them.
Expand All @@ -140,7 +114,7 @@ namespace clang {
// Determine if a variable is used in a fact.
bool IsVarInFact(const AbstractFact *Fact, const VarDecl *Var) const;

// Determine if two facts equal. First check if the comparision is check before,
// Determine if two facts are equal. First check if the comparison is checked before,
// otherwise, perform the real check.
bool IsFactEqual(const AbstractFact *Fact1, const AbstractFact *Fact2);

Expand Down Expand Up @@ -207,24 +181,25 @@ namespace clang {
Lexicographic Lex;
llvm::raw_ostream &OS;
AvailableFactsUtil AFUtil;

class ElevatedCFGBlock {
public:
using EdgeFactsTy = llvm::DenseMap<const ElevatedCFGBlock *, AbstractFactListTy>;

const CFGBlock *Block;

// Block-wise
// Block-wise.
AbstractFactListTy In;
KillVarSetTy Kill;

// Edge-wise
// Edge-wise.
EdgeFactsTy Gen, Out;
// Edge-wise (but on a Block)
// Edge-wise (stored at its starting block).
AbstractFactListTy GenAllSucc, OutAllSucc;

// Statement-wise
StmtFactsMapTy StmtGen;
StmtKillVarSetTy StmtKill;
// // Statement-wise
// StmtFactsMapTy StmtGen;
// StmtKillVarSetTy StmtKill;

// A mapping from a statement to its previous statement in a block.
StmtMapTy PrevStmtMap;
Expand All @@ -250,7 +225,15 @@ namespace clang {

// Allocated facts in the analysis
AbstractFactListTy FactsCreated;


// Stateful accumulated fact sets in a block.
// This is for called from the outside for continuous statementts in a fixed block.
AbstractFactListTy AccuGen;
KillVarSetTy AccuKill;
const CFGBlock *AccuBlock;
ElevatedCFGBlock *AccuEB;
// const CFGBlock::const_iterator *AccuStmtIt;

public:
// Top is a special bounds expression that denotes the super set of all
// bounds expressions.
Expand All @@ -259,10 +242,12 @@ namespace clang {
AvailableWhereFactsAnalysis(Sema &SemaRef, CFG *Cfg) :
SemaRef(SemaRef), Cfg(Cfg), Ctx(SemaRef.Context),
Lex(Lexicographic(Ctx, nullptr)), OS(llvm::outs()),
AFUtil(AvailableFactsUtil(SemaRef, Cfg, Ctx, Lex)) {}
AFUtil(AvailableFactsUtil(SemaRef, Cfg, SemaRef.Context, Lex)) {}

~AvailableWhereFactsAnalysis();


void GetFacts(const CFGBlock *Block, AbstractFactListTy &Facts);

// Run the dataflow analysis.
// @param[in] FD is the current function.
void Analyze(FunctionDecl *FD, StmtSetTy NestedStmts);
Expand All @@ -272,7 +257,17 @@ namespace clang {
// @param[in] FD is the current function.
void DumpAvailableFacts(FunctionDecl *FD);

// Get the Out set for the statement.
AbstractFactListTy GetStmtOut(const CFGBlock *EB, const Stmt *CurrStmt);

// Get the In set for the statement.
AbstractFactListTy GetStmtIn(const CFGBlock *EB, const Stmt *CurrStmt);

private:
// Add the successors of the current block to WorkList.
// @param[in] CurrBlock is the current block.
// @param[in] WorkList stores the blocks remaining to be processed for the
// fixpoint computation.
void AddSuccsToWorkList(const CFGBlock *CurrBlock, WorkListTy &WorkList);

// Compute Gen and Kill sets for the entry block.
Expand All @@ -288,13 +283,19 @@ namespace clang {
// @param[in] EB is the current ElevatedCFGBlock.
// @param[in] CurrStmt is the current statement.
void ComputeStmtGenKillSets(ElevatedCFGBlock *EB, const Stmt *CurrStmt,
StmtSetTy NestedStmts);
StmtSetTy NestedStmts,
AbstractFactListTy &Gen,
KillVarSetTy &Kill);

// Collect the facts in the variable declaration.
// @param[in] Gen is the container for the facts set.
// @param[in] Gen is the container for the Kill set.
// @param[in] V is the variable declaration to act.
void CollectFactsInDecl(AbstractFactListTy &Gen,
KillVarSetTy &Kill,
const VarDecl *V);

// Collect the facts and killed varibles in the where clauses.
// Collect the facts in the where clauses.
// @param[in] Gen is the container for the facts set.
// @param[in] Gen is the container for the Kill set.
// @param[in] WC is the where clause to act.
Expand All @@ -319,12 +320,6 @@ namespace clang {
// otherwise.
bool ComputeOutSet(ElevatedCFGBlock *EB, WorkListTy &WorkList);

// Get the Out set for the statement.
AbstractFactListTy GetStmtOut(ElevatedCFGBlock *EB, const Stmt *CurrStmt) const;

// Get the In set for the statement.
AbstractFactListTy GetStmtIn(ElevatedCFGBlock *EB, const Stmt *CurrStmt) const;

// Order the blocks by block number to get a deterministic iteration order
// for the blocks.
// @return Blocks ordered by block number from higher to lower since block
Expand Down
39 changes: 39 additions & 0 deletions clang/include/clang/Sema/FactUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===----------- FactUtils.h: Utility functions for facts ----------===//
//
// The LLVM Compiler Infrastructure
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===------------------------------------------------------------------===//
//
// This file defines the utility functions for facts.
//
//===------------------------------------------------------------------===//

#ifndef LLVM_CLANG_FACTUTILS_H
#define LLVM_CLANG_FACTUTILS_H

#include "clang/AST/Expr.h"
#include "clang/Sema/Sema.h"

namespace clang {

class FactPrinter {
public:
// TODO: should not be here
// Top is a special bounds expression that denotes the super set of all
// bounds expressions.
static constexpr RangeBoundsExpr *BoundsTop = nullptr;

// Pretty print an abstract fact.
static void PrintPretty(Sema &S, const AbstractFact *Fact);

// Pretty print a list of abstract fact.
static void PrintPretty(Sema &S, const AbstractFactListTy &Facts);
};

} // end namespace clang

#endif
23 changes: 23 additions & 0 deletions clang/lib/AST/ExprUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,29 @@ std::pair<Expr *, Expr *> ExprUtil::SplitByLValueCount(Sema &S, Expr *LValue,
return Pair;
}

Expr *ExprUtil::IgnoreCasts(Lexicographic &Lex, ASTContext &Ctx, const Expr *E) {
return Lex.IgnoreValuePreservingOperations(Ctx, const_cast<Expr *>(E));
}

Expr *ExprUtil::TranspareCasts(Lexicographic &Lex, ASTContext &Ctx, const Expr *E) {
Expr *Pre = Lex.IgnoreValuePreservingOperations(Ctx, const_cast<Expr *>(E));
Expr *Post = Pre;
if (auto *CE = dyn_cast<CastExpr>(Pre)) {
if (CE->getCastKind() == CastKind::CK_IntegralCast)
Post = CE->getSubExpr();
}

if (auto *CE = dyn_cast<CastExpr>(Pre))
if (CE->getCastKind() == CastKind::CK_LValueToRValue)
Post = CE->getSubExpr();

if (Pre == Post) {
return Post;
} else {
return TranspareCasts(Lex, Ctx, Post);
}
}

namespace {
class LValueCountHelper : public RecursiveASTVisitor<LValueCountHelper> {
private:
Expand Down
Loading

0 comments on commit f1aa427

Please sign in to comment.