11#include " BE/Base/sanity.h"
22
33#include < set>
4+ #include < vector>
45
56#include " BE/Base/cfg.h"
7+ #include " BE/Base/ir.h"
68#include " BE/Base/serialize.h"
79
810namespace cwerg ::base {
911
10- void BblCheck (Bbl bbl, Fun fun) {
12+ class FunArgState {
13+ public:
14+ FunArgState () = default ;
15+
16+ void HandleProlog (Fun fun) {
17+ FillPopArgs (FunNumInputTypes (fun), FunInputTypes (fun));
18+ }
19+
20+ void HandleIns (Ins ins, Bbl bbl, Fun fun) {
21+ switch (InsOPC (ins)) {
22+ case OPC::POPARG: {
23+ if (num_pop_args_ == 0 ) {
24+ CHECK (false , " too many pop args in " << Name (fun));
25+ }
26+ DK expected = pop_args_[num_pop_args_ - 1 ];
27+ --num_pop_args_;
28+ DK actual = RegOrConstKind (InsOperand (ins, 0 ));
29+ CHECK (expected == actual, " unexpected pop arg type in "
30+ << Name (fun) << " : expected "
31+ << EnumToString (expected) << " got "
32+ << EnumToString (actual));
33+ break ;
34+ }
35+ case OPC::PUSHARG: {
36+ CHECK (num_pop_args_ == 0 , " orphan pop args in " << Name (fun));
37+ DK dk = RegOrConstKind (InsOperand (ins, 0 ));
38+ CHECK (num_push_args_ < MAX_PARAMETERS,
39+ " too many push args in " << Name (fun));
40+ push_args_[num_push_args_] = dk;
41+ ++num_push_args_;
42+ break ;
43+ }
44+ case OPC::RET:
45+ CHECK (num_pop_args_ == 0 , " orphan pop args " << Name (fun));
46+ ConsumePushArgs (FunNumOutputTypes (fun), FunOutputTypes (fun),
47+ Fun (HandleInvalid), fun);
48+ break ;
49+ case OPC::JSR:
50+ case OPC::BSR:
51+ case OPC::SYSCALL: {
52+ Fun callee = InsCallee (ins);
53+ CHECK (num_pop_args_ == 0 , " orphan pop args in " << Name (fun));
54+ ConsumePushArgs (FunNumInputTypes (callee), FunInputTypes (callee), callee,
55+ fun);
56+ FillPopArgs (FunNumOutputTypes (callee), FunOutputTypes (callee));
57+ if (FunBblList::IsEmpty (callee)) {
58+ CHECK (FunKind (callee) == FUN_KIND::BUILTIN ||
59+ FunKind (callee) == FUN_KIND::SIGNATURE,
60+ " undefined function " << Name (callee) << " in " << Name (fun));
61+ }
62+ break ;
63+ }
64+ default :
65+ CHECK (num_pop_args_ == 0 , " orphan pop args " << Name (fun));
66+ CHECK (num_push_args_ == 0 , " orphan push args " << Name (fun));
67+ break ;
68+ }
69+ }
70+
71+ private:
72+ void ConsumePushArgs (int n, DK* dks, Fun callee, Fun caller) {
73+ if (num_push_args_ != n) {
74+ if (callee == HandleInvalid) {
75+ CHECK (false , " In " << Name (caller) << " epilog: expected " << n
76+ << " push args, got " << num_push_args_);
77+ } else {
78+ CHECK (false , " In " << Name (caller) << " calling " << Name (callee)
79+ << " : expected " << n << " push args, got "
80+ << num_push_args_);
81+ }
82+ }
83+ for (int i = 0 ; i < n; i++) {
84+ if (push_args_[i] != dks[n - 1 - i]) {
85+ if (callee == HandleInvalid) {
86+ CHECK (false , " In caller " << Name (caller) << " epilog: expected push arg "
87+ << i << " to be "
88+ << EnumToString (dks[n - 1 - i]) << " got "
89+ << EnumToString (push_args_[i]));
90+ } else {
91+ CHECK (false , " In caller " << Name (caller) << " calling "
92+ << Name (callee) << " : expected push arg "
93+ << i << " to be "
94+ << EnumToString (dks[n - 1 - i]) << " got "
95+ << EnumToString (push_args_[i]));
96+ }
97+ }
98+ }
99+ num_push_args_ = 0 ;
100+ }
101+
102+ void FillPopArgs (int n, DK* dks) {
103+ for (int i = 0 ; i < n; i++) {
104+ DK dk = dks[n - i - 1 ];
105+ pop_args_[i] = dk;
106+ }
107+ num_pop_args_ = n;
108+ }
109+
110+ void FillPushArgs (int n, DK* dks) {
111+ for (int i = 0 ; i < n; i++) {
112+ DK dk = dks[n - i - 1 ];
113+ push_args_[i] = dk;
114+ }
115+ num_push_args_ = n;
116+ }
117+
118+ DK pop_args_[MAX_PARAMETERS];
119+ DK push_args_[MAX_PARAMETERS];
120+ int num_pop_args_ = 0 ;
121+ int num_push_args_ = 0 ;
122+ };
123+
124+ void BblCheck (Bbl bbl, Fun fun, FunArgState* state, bool check_push_pop) {
11125 uint32_t count = 0 ;
12126 for (Ins ins : BblInsIter (bbl)) {
13127 Ins prev = BblInsList::Prev (ins);
@@ -32,20 +146,18 @@ void BblCheck(Bbl bbl, Fun fun) {
32146 CHECK (false , " bbl corruption in " << Name (fun) << " at pos " << count);
33147 }
34148 }
35-
36- if (InsOpcode (ins).IsCall ()) {
37- Fun callee = InsCallee (ins);
38- if (FunBblList::IsEmpty (callee)) {
39- CHECK (FunKind (callee) == FUN_KIND::BUILTIN ||
40- FunKind (callee) == FUN_KIND::SIGNATURE,
41- " undefined function " << Name (callee) << " in " << Name (fun));
42- }
149+ if (check_push_pop) {
150+ state->HandleIns (ins, bbl, fun);
43151 }
44152 ++count;
45153 }
46154}
47155
48- void FunCheck (Fun fun) {
156+ void FunCheck (Fun fun, bool check_cfg, bool check_push_pop,
157+ bool check_fallthroughs) {
158+ FunArgState state;
159+ state.HandleProlog (fun);
160+
49161 std::set<Bbl> bbls;
50162 for (Bbl bbl : FunBblIter (fun)) {
51163 bbls.insert (bbl);
@@ -98,37 +210,14 @@ void FunCheck(Fun fun) {
98210 Bbl pred = EdgPredBbl (edg);
99211 Bbl succ = EdgSuccBbl (edg);
100212 CHECK (bbls.find (pred) != bbls.end (),
101- " bad " << Name (pred) << " -> " << Name (succ));
213+ " bad 1 " << Name (pred) << " -> " << Name (succ) << " " << Name (fun ));
102214 CHECK (bbls.find (succ) != bbls.end (),
103- " bad " << Name (pred) << " -> " << Name (succ));
104- CHECK (pred == bbl,
105- " bad " << Name (bbl) << " : " << Name (pred) << " -> " << Name (succ));
106- }
107-
108- BblCheck (bbl, fun);
109- }
110- }
111-
112- void UnitCheck (Unit unit) {
113- for (Fun fun : UnitFunIter (unit)) {
114- Fun prev = UnitFunList::Prev (fun);
115- Fun next = UnitFunList::Next (fun);
116-
117- if (UnitFunList::IsSentinel (prev)) {
118- CHECK (prev == unit, " " );
119- CHECK (UnitFunList::Head (unit) == fun, " " );
120- } else {
121- CHECK (UnitFunList::Next (prev) == fun, " " );
122- }
123-
124- if (UnitFunList::IsSentinel (next)) {
125- CHECK (next == unit, " " );
126- CHECK (UnitFunList::Tail (unit) == fun, " " );
127- } else {
128- CHECK (UnitFunList::Prev (next) == fun, " " );
215+ " bad 2 " << Name (pred) << " -> " << Name (succ) << " " << Name (fun));
216+ CHECK (pred == bbl, " bad 3 " << Name (bbl) << " : " << Name (pred) << " -> "
217+ << Name (succ) << " " << Name (fun));
129218 }
130219
131- FunCheck ( fun);
220+ BblCheck (bbl, fun, &state, check_push_pop );
132221 }
133222}
134223
0 commit comments