Skip to content

Commit ce12662

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:ee765b0c94df7e636d9739216b1646d3a2d3b5db into amd-gfx:cf4a0e80e87c
Local branch amd-gfx cf4a0e8 Merged main:df5804aec48f99704ef26c740e19deaa4072fe27 into amd-gfx:7c50b9e88fc0 Remote branch main ee765b0 [NewPM] Add pass options for `InternalizePass` to preserve GVs. (llvm#91334)
2 parents cf4a0e8 + ee765b0 commit ce12662

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+723
-520
lines changed

clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h

Lines changed: 73 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/DeclBase.h"
2020
#include "clang/AST/Expr.h"
2121
#include "clang/AST/Type.h"
22+
#include "clang/Analysis/FlowSensitive/ASTOps.h"
2223
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
2324
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
2425
#include "clang/Analysis/FlowSensitive/Formula.h"
@@ -30,9 +31,11 @@
3031
#include "llvm/ADT/MapVector.h"
3132
#include "llvm/Support/Compiler.h"
3233
#include "llvm/Support/ErrorHandling.h"
34+
#include <cassert>
3335
#include <memory>
3436
#include <type_traits>
3537
#include <utility>
38+
#include <vector>
3639

3740
namespace clang {
3841
namespace dataflow {
@@ -155,32 +158,40 @@ class Environment {
155158

156159
/// Creates an environment that uses `DACtx` to store objects that encompass
157160
/// the state of a program.
158-
explicit Environment(DataflowAnalysisContext &DACtx);
161+
explicit Environment(DataflowAnalysisContext &DACtx)
162+
: DACtx(&DACtx),
163+
FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
164+
165+
/// Creates an environment that uses `DACtx` to store objects that encompass
166+
/// the state of a program, with `S` as the statement to analyze.
167+
Environment(DataflowAnalysisContext &DACtx, Stmt &S) : Environment(DACtx) {
168+
InitialTargetStmt = &S;
169+
}
170+
171+
/// Creates an environment that uses `DACtx` to store objects that encompass
172+
/// the state of a program, with `FD` as the function to analyze.
173+
///
174+
/// Requirements:
175+
///
176+
/// The function must have a body, i.e.
177+
/// `FunctionDecl::doesThisDecalarationHaveABody()` must be true.
178+
Environment(DataflowAnalysisContext &DACtx, const FunctionDecl &FD)
179+
: Environment(DACtx, *FD.getBody()) {
180+
assert(FD.doesThisDeclarationHaveABody());
181+
InitialTargetFunc = &FD;
182+
}
159183

160184
// Copy-constructor is private, Environments should not be copied. See fork().
161185
Environment &operator=(const Environment &Other) = delete;
162186

163187
Environment(Environment &&Other) = default;
164188
Environment &operator=(Environment &&Other) = default;
165189

166-
/// Creates an environment that uses `DACtx` to store objects that encompass
167-
/// the state of a program.
168-
///
169-
/// If `DeclCtx` is a function, initializes the environment with symbolic
170-
/// representations of the function parameters.
171-
///
172-
/// If `DeclCtx` is a non-static member function, initializes the environment
173-
/// with a symbolic representation of the `this` pointee.
174-
Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx);
175-
176190
/// Assigns storage locations and values to all parameters, captures, global
177-
/// variables, fields and functions referenced in the function currently being
178-
/// analyzed.
179-
///
180-
/// Requirements:
191+
/// variables, fields and functions referenced in the `Stmt` or `FunctionDecl`
192+
/// passed to the constructor.
181193
///
182-
/// The function must have a body, i.e.
183-
/// `FunctionDecl::doesThisDecalarationHaveABody()` must be true.
194+
/// If no `Stmt` or `FunctionDecl` was supplied, this function does nothing.
184195
void initialize();
185196

186197
/// Returns a new environment that is a copy of this one.
@@ -193,7 +204,7 @@ class Environment {
193204
/// forked flow condition references the original).
194205
Environment fork() const;
195206

196-
/// Creates and returns an environment to use for an inline analysis of the
207+
/// Creates and returns an environment to use for an inline analysis of the
197208
/// callee. Uses the storage location from each argument in the `Call` as the
198209
/// storage location for the corresponding parameter in the callee.
199210
///
@@ -365,46 +376,51 @@ class Environment {
365376
RecordStorageLocation &
366377
getResultObjectLocation(const Expr &RecordPRValue) const;
367378

368-
/// Returns the return value of the current function. This can be null if:
379+
/// Returns the return value of the function currently being analyzed.
380+
/// This can be null if:
369381
/// - The function has a void return type
370382
/// - No return value could be determined for the function, for example
371383
/// because it calls a function without a body.
372384
///
373385
/// Requirements:
374-
/// The current function must have a non-reference return type.
386+
/// The current analysis target must be a function and must have a
387+
/// non-reference return type.
375388
Value *getReturnValue() const {
376389
assert(getCurrentFunc() != nullptr &&
377390
!getCurrentFunc()->getReturnType()->isReferenceType());
378391
return ReturnVal;
379392
}
380393

381-
/// Returns the storage location for the reference returned by the current
382-
/// function. This can be null if function doesn't return a single consistent
383-
/// reference.
394+
/// Returns the storage location for the reference returned by the function
395+
/// currently being analyzed. This can be null if the function doesn't return
396+
/// a single consistent reference.
384397
///
385398
/// Requirements:
386-
/// The current function must have a reference return type.
399+
/// The current analysis target must be a function and must have a reference
400+
/// return type.
387401
StorageLocation *getReturnStorageLocation() const {
388402
assert(getCurrentFunc() != nullptr &&
389403
getCurrentFunc()->getReturnType()->isReferenceType());
390404
return ReturnLoc;
391405
}
392406

393-
/// Sets the return value of the current function.
407+
/// Sets the return value of the function currently being analyzed.
394408
///
395409
/// Requirements:
396-
/// The current function must have a non-reference return type.
410+
/// The current analysis target must be a function and must have a
411+
/// non-reference return type.
397412
void setReturnValue(Value *Val) {
398413
assert(getCurrentFunc() != nullptr &&
399414
!getCurrentFunc()->getReturnType()->isReferenceType());
400415
ReturnVal = Val;
401416
}
402417

403-
/// Sets the storage location for the reference returned by the current
404-
/// function.
418+
/// Sets the storage location for the reference returned by the function
419+
/// currently being analyzed.
405420
///
406421
/// Requirements:
407-
/// The current function must have a reference return type.
422+
/// The current analysis target must be a function and must have a reference
423+
/// return type.
408424
void setReturnStorageLocation(StorageLocation *Loc) {
409425
assert(getCurrentFunc() != nullptr &&
410426
getCurrentFunc()->getReturnType()->isReferenceType());
@@ -641,23 +657,21 @@ class Environment {
641657
/// (or the flow condition is overly constraining) or if the solver times out.
642658
bool allows(const Formula &) const;
643659

644-
/// Returns the `DeclContext` of the block being analysed, if any. Otherwise,
645-
/// returns null.
646-
const DeclContext *getDeclCtx() const { return CallStack.back(); }
647-
648660
/// Returns the function currently being analyzed, or null if the code being
649661
/// analyzed isn't part of a function.
650662
const FunctionDecl *getCurrentFunc() const {
651-
return dyn_cast<FunctionDecl>(getDeclCtx());
663+
return CallStack.empty() ? InitialTargetFunc : CallStack.back();
652664
}
653665

654-
/// Returns the size of the call stack.
666+
/// Returns the size of the call stack, not counting the initial analysis
667+
/// target.
655668
size_t callStackSize() const { return CallStack.size(); }
656669

657670
/// Returns whether this `Environment` can be extended to analyze the given
658-
/// `Callee` (i.e. if `pushCall` can be used), with recursion disallowed and a
659-
/// given `MaxDepth`.
660-
bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const;
671+
/// `Callee` (i.e. if `pushCall` can be used).
672+
/// Recursion is not allowed. `MaxDepth` is the maximum size of the call stack
673+
/// (i.e. the maximum value that `callStackSize()` may assume after the call).
674+
bool canDescend(unsigned MaxDepth, const FunctionDecl *Callee) const;
661675

662676
/// Returns the `DataflowAnalysisContext` used by the environment.
663677
DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; }
@@ -719,15 +733,20 @@ class Environment {
719733
ArrayRef<const Expr *> Args);
720734

721735
/// Assigns storage locations and values to all global variables, fields
722-
/// and functions referenced in `FuncDecl`. `FuncDecl` must have a body.
723-
void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl);
736+
/// and functions in `Referenced`.
737+
void initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced);
724738

725739
static PrValueToResultObject
726740
buildResultObjectMap(DataflowAnalysisContext *DACtx,
727741
const FunctionDecl *FuncDecl,
728742
RecordStorageLocation *ThisPointeeLoc,
729743
RecordStorageLocation *LocForRecordReturnVal);
730744

745+
static PrValueToResultObject
746+
buildResultObjectMap(DataflowAnalysisContext *DACtx, Stmt *S,
747+
RecordStorageLocation *ThisPointeeLoc,
748+
RecordStorageLocation *LocForRecordReturnVal);
749+
731750
// `DACtx` is not null and not owned by this object.
732751
DataflowAnalysisContext *DACtx;
733752

@@ -736,11 +755,20 @@ class Environment {
736755
// shared between environments in the same call.
737756
// https://github.com/llvm/llvm-project/issues/59005
738757

739-
// `DeclContext` of the block being analysed if provided.
740-
std::vector<const DeclContext *> CallStack;
758+
// The stack of functions called from the initial analysis target.
759+
std::vector<const FunctionDecl *> CallStack;
760+
761+
// Initial function to analyze, if a function was passed to the constructor.
762+
// Null otherwise.
763+
const FunctionDecl *InitialTargetFunc = nullptr;
764+
// Top-level statement of the initial analysis target.
765+
// If a function was passed to the constructor, this is its body.
766+
// If a statement was passed to the constructor, this is that statement.
767+
// Null if no analysis target was passed to the constructor.
768+
Stmt *InitialTargetStmt = nullptr;
741769

742770
// Maps from prvalues of record type to their result objects. Shared between
743-
// all environments for the same function.
771+
// all environments for the same analysis target.
744772
// FIXME: It's somewhat unsatisfactory that we have to use a `shared_ptr`
745773
// here, though the cost is acceptable: The overhead of a `shared_ptr` is
746774
// incurred when it is copied, and this happens only relatively rarely (when
@@ -749,7 +777,7 @@ class Environment {
749777
std::shared_ptr<PrValueToResultObject> ResultObjectMap;
750778

751779
// The following three member variables handle various different types of
752-
// return values.
780+
// return values when the current analysis target is a function.
753781
// - If the return type is not a reference and not a record: Value returned
754782
// by the function.
755783
Value *ReturnVal = nullptr;
@@ -762,7 +790,7 @@ class Environment {
762790
RecordStorageLocation *LocForRecordReturnVal = nullptr;
763791

764792
// The storage location of the `this` pointee. Should only be null if the
765-
// function being analyzed is only a function and not a method.
793+
// analysis target is not a method.
766794
RecordStorageLocation *ThisPointeeLoc = nullptr;
767795

768796
// Maps from declarations and glvalue expression to storage locations that are

0 commit comments

Comments
 (0)