1//===- PointerFlowAnalysis.cpp - WPA for PointerFlow ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h"
10#include "SSAFAnalysesCommon.h"
11#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
12#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h"
13#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
14#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
15#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
16#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
17#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
18#include "llvm/ADT/STLFunctionalExtras.h"
19#include "llvm/ADT/iterator_range.h"
20#include "llvm/Support/Error.h"
21#include "llvm/Support/JSON.h"
22#include <memory>
23
24using namespace clang::ssaf;
25using namespace llvm;
26
27namespace {
28
29//===----------------------------------------------------------------------===//
30// PointerFlowAnalysis---converts PointerFlowEntitySummary(s) in an LUSummary to
31// a PointerFlowAnalysisResult
32//===----------------------------------------------------------------------===//
33
34// Serialized as a flat array of alternating [EntityId, EdgesArray, ...] pairs.
35json::Object
36serializePointerFlowAnalysisResult(const PointerFlowAnalysisResult &R,
37 JSONFormat::EntityIdToJSONFn IdToJSON) {
38 json::Array Content;
39
40 for (const auto &[Id, EntityEdges] : R.Edges) {
41 Content.push_back(E: IdToJSON(Id));
42 Content.push_back(E: json::Value(edgeSetToJSON(Edges: EntityEdges, IdToJSON)));
43 }
44
45 json::Object Result;
46
47 Result[PointerFlowAnalysisResultName] = std::move(Content);
48 return Result;
49}
50
51Expected<std::unique_ptr<AnalysisResult>> deserializePointerFlowAnalysisResult(
52 const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
53 const json::Array *Content = Obj.getArray(K: PointerFlowAnalysisResultName);
54
55 if (!Content)
56 return makeSawButExpectedError(Saw: Obj, Expected: "an object with a key %s",
57 ExpectedArgs: PointerFlowAnalysisResultName.data());
58
59 if (Content->size() % 2 != 0)
60 return makeSawButExpectedError(Saw: *Content,
61 Expected: "an even number of elements, got %lu",
62 ExpectedArgs: static_cast<size_t>(Content->size()));
63
64 std::map<EntityId, EdgeSet> Edges;
65
66 for (size_t I = 0; I < Content->size(); I += 2) {
67 const json::Object *IdData = (*Content)[I].getAsObject();
68
69 if (!IdData)
70 return makeSawButExpectedError(Saw: (*Content)[I],
71 Expected: "an object representing EntityId");
72
73 auto Id = IdFromJSON(*IdData);
74
75 if (!Id)
76 return Id.takeError();
77
78 const json::Array *EdgesData = (*Content)[I + 1].getAsArray();
79
80 if (!EdgesData)
81 return makeSawButExpectedError(Saw: (*Content)[I + 1],
82 Expected: "an array of arrays representing EdgeSet");
83
84 auto EntityEdges = edgeSetFromJSON(EdgesData: *EdgesData, IdFromJSON);
85
86 if (!EntityEdges)
87 return EntityEdges.takeError();
88 Edges[*Id] = std::move(*EntityEdges);
89 }
90
91 auto Ret = std::make_unique<PointerFlowAnalysisResult>();
92
93 Ret->Edges = std::move(Edges);
94 return Ret;
95}
96
97JSONFormat::AnalysisResultRegistry::Add<PointerFlowAnalysisResult>
98 RegisterPointerFlowResultForJSON(serializePointerFlowAnalysisResult,
99 deserializePointerFlowAnalysisResult);
100
101class PointerFlowAnalysis final
102 : public SummaryAnalysis<PointerFlowAnalysisResult,
103 PointerFlowEntitySummary> {
104public:
105 llvm::Error add(EntityId Id,
106 const PointerFlowEntitySummary &Summary) override {
107 auto EdgesOfEntity = getEdges(Summary);
108
109 getResult().Edges[Id] = EdgeSet(EdgesOfEntity.begin(), EdgesOfEntity.end());
110 return llvm::Error::success();
111 }
112};
113
114AnalysisRegistry::Add<PointerFlowAnalysis>
115 RegisterPointerFlowAnalysis("Whole-program pointer flow analysis");
116
117} // namespace
118
119namespace clang::ssaf {
120// NOLINTNEXTLINE(misc-use-internal-linkage)
121volatile int PointerFlowAnalysisAnchorSource = 0;
122} // namespace clang::ssaf
123