P4C
The P4 Compiler
Loading...
Searching...
No Matches
halsteadMetrics.h
1/*
2Collects basic Halstead metrics (unique and total operators and operands)
3of the compiled program, and calculates derived Halstead metrics
4(vocabulary, length, difficulty, volume, effort, delivered bugs) at
5the end of traversal. The collection process is based on rules,
6which were adapted from the rules for collecting Halstead metrics in C:
7
8- Identifier and control block declarations are not considered.
9- Constructor calls are considered operators.
10- All variables, constants, and literals are considered operands.
11- Local variables and constants with identical names in different blocks are considered distinct
12operands.
13- Structure fields are considered as global operands, and are only counted when used.
14- Control flow statements (if, select, transition, etc.) are considered operators.
15- Function calls, method calls and action invocations are considered operators.
16- Built-in functions (extract, clear, get, etc.) are considered operators.
17- Square brackets and dots are considered operators.
18- Unary and binary versions of operators such as + and - are counted separately.
19- State names in transition statements are considered operands (since they are similar to GOTO
20statements in C)
21*/
22
23#ifndef FRONTENDS_P4_METRICS_HALSTEADMETRICS_H_
24#define FRONTENDS_P4_METRICS_HALSTEADMETRICS_H_
25
26#include <cmath>
27#include <string>
28#include <unordered_set>
29#include <vector>
30
31#include "frontends/p4/metrics/metricsStructure.h"
32#include "ir/ir.h"
33#include "lib/log.h"
34
35using namespace P4::literals;
36
37namespace P4 {
38
39class HalsteadMetricsPass : public Inspector {
40 private:
41 HalsteadMetrics &metrics;
42 std::unordered_set<cstring> uniqueUnaryOperators;
43 std::unordered_set<cstring> uniqueBinaryOperators;
44 std::unordered_multiset<cstring> uniqueOperands;
45 std::unordered_set<cstring> structFields; // Field names of the defined structures.
46 std::unordered_set<cstring> uniqueFields; // Structure fields that were used in the program.
47 std::vector<std::unordered_set<cstring>> scopedOperands; // Operands separated by scopes.
48 const std::unordered_set<P4::cstring> reservedKeywords = {
49 "extract"_cs, "emit"_cs, "isValid"_cs, "setValid"_cs, "setInvalid"_cs,
50 "push_front"_cs, "pop_front"_cs, "next"_cs, "last"_cs, "apply"_cs,
51 "hit"_cs, "miss"_cs, "action_run"_cs, "accept"_cs, "mark_to_drop"_cs,
52 "read"_cs, "write"_cs, "count"_cs, "execute"_cs, "clear"_cs,
53 "update"_cs, "get"_cs, "verify"_cs, "clone"_cs, "resubmit"_cs,
54 "recirculate"_cs, "transition"_cs, "size"_cs, "max_length"_cs, "length"_cs};
55
56 const std::unordered_set<P4::cstring> matchTypes = {"exact"_cs, "lpm"_cs, "ternary"_cs,
57 "range"_cs, "optional"_cs};
58
59 // Helper methods.
60
61 void addOperand(const cstring &operand);
62 void addUnaryOperator(const cstring &op);
63 void addBinaryOperator(const cstring &op);
64
65 public:
66 explicit HalsteadMetricsPass(Metrics &metricsRef) : metrics(metricsRef.halsteadMetrics) {
67 setName("HalsteadMetricsPass");
68 }
69
70 // Scope handling.
71
72 bool preorder(const IR::P4Control * /*control*/) override;
73 void postorder(const IR::P4Control * /*control*/) override;
74 bool preorder(const IR::P4Parser * /*parser*/) override;
75 void postorder(const IR::P4Parser * /*parser*/) override;
76 bool preorder(const IR::Function * /*function*/) override;
77 void postorder(const IR::Function * /*function*/) override;
78
79 // Operand and operator data collection.
80
81 void postorder(const IR::Type_Header *headerType) override;
82 void postorder(const IR::Type_Struct *structType) override;
83 bool preorder(const IR::PathExpression *pathExpr) override;
84 bool preorder(const IR::Member *member) override;
85 void postorder(const IR::Constant *constant) override;
86 void postorder(const IR::ConstructorCallExpression *ctorCall) override;
87 bool preorder(const IR::MethodCallExpression *methodCall) override;
88 void postorder(const IR::AssignmentStatement * /*stmt*/) override;
89 void postorder(const IR::IfStatement *stmt) override;
90 void postorder(const IR::SwitchStatement * /*stmt*/) override;
91 void postorder(const IR::SwitchCase * /*case*/) override;
92 void postorder(const IR::ForStatement * /*stmt*/) override;
93 void postorder(const IR::ForInStatement * /*stmt*/) override;
94 void postorder(const IR::ReturnStatement * /*stmt*/) override;
95 void postorder(const IR::ExitStatement * /*stmt*/) override;
96 bool preorder(const IR::Operation_Unary *op) override;
97 void postorder(const IR::Operation_Binary *op) override;
98 void postorder(const IR::ParserState *state) override;
99 void postorder(const IR::SelectExpression * /*selectExpr*/) override;
100 bool preorder(const IR::SelectCase *selectCase) override;
101 void postorder(const IR::P4Table *table) override;
102
104 void postorder(const IR::P4Program * /*program*/) override;
105};
106
107} // namespace P4
108
109#endif /* FRONTENDS_P4_METRICS_HALSTEADMETRICS_H_ */
Definition visitor.h:413
Definition cstring.h:85
Definition cstring.h:80
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition metricsStructure.h:97
Definition metricsStructure.h:119