1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "abs_int_inl.h"
17 #include "handle_gen.h"
18
19 namespace ark::verifier {
20
IsRegDefined(int reg)21 bool AbsIntInstructionHandler::IsRegDefined(int reg)
22 {
23 bool isDefined = ExecCtx().CurrentRegContext().IsRegDefined(reg);
24 #ifndef NDEBUG
25 if (!isDefined) {
26 if (!ExecCtx().CurrentRegContext().WasConflictOnReg(reg)) {
27 SHOW_MSG(UndefinedRegister)
28 LOG_VERIFIER_UNDEFINED_REGISTER(RegisterName(reg, true));
29 END_SHOW_MSG();
30 } else {
31 SHOW_MSG(RegisterTypeConflict)
32 LOG_VERIFIER_REGISTER_TYPE_CONFLICT(RegisterName(reg, false));
33 END_SHOW_MSG();
34 }
35 }
36 #endif
37 return isDefined;
38 }
39
CheckRegType(int reg,Type tgtType)40 bool AbsIntInstructionHandler::CheckRegType(int reg, Type tgtType)
41 {
42 if (!IsRegDefined(reg)) {
43 return false;
44 }
45 auto type = GetRegType(reg);
46 if (CheckType(type, tgtType)) {
47 return true;
48 }
49
50 SHOW_MSG(BadRegisterType)
51 LOG_VERIFIER_BAD_REGISTER_TYPE(RegisterName(reg, true), ToString(type), ToString(tgtType));
52 END_SHOW_MSG();
53 return false;
54 }
55
GetReg(int regIdx)56 const AbstractTypedValue &AbsIntInstructionHandler::GetReg(int regIdx)
57 {
58 return context_.ExecCtx().CurrentRegContext()[regIdx];
59 }
60
GetRegType(int regIdx)61 Type AbsIntInstructionHandler::GetRegType(int regIdx)
62 {
63 return GetReg(regIdx).GetAbstractType();
64 }
65
SetReg(int regIdx,const AbstractTypedValue & val)66 void AbsIntInstructionHandler::SetReg(int regIdx, const AbstractTypedValue &val)
67 {
68 if (job_->Options().ShowRegChanges()) {
69 PandaString prevAtvImage {"<none>"};
70 if (ExecCtx().CurrentRegContext().IsRegDefined(regIdx)) {
71 prevAtvImage = ToString(&GetReg(regIdx));
72 }
73 auto newAtvImage = ToString(&val);
74 LOG_VERIFIER_DEBUG_REGISTER_CHANGED(RegisterName(regIdx), prevAtvImage, newAtvImage);
75 }
76 // RegContext extends flexibly for any number of registers, though on AbsInt instruction
77 // handling stage it is not a time to add a new register! The regsiter set (vregs and aregs)
78 // is normally initialized on PrepareVerificationContext.
79 if (!context_.ExecCtx().CurrentRegContext().IsValid(regIdx)) {
80 auto const *method = job_->JobMethod();
81 auto numVregs = method->GetNumVregs();
82 auto numAregs = GetTypeSystem()->GetMethodSignature(method)->args.size();
83 if (regIdx > (int)(numVregs + numAregs)) {
84 LOG_VERIFIER_UNDEFINED_REGISTER(RegisterName(regIdx, true));
85 SET_STATUS_FOR_MSG(UndefinedRegister, ERROR);
86 }
87 }
88 context_.ExecCtx().CurrentRegContext()[regIdx] = val;
89 }
90
SetReg(int regIdx,Type type)91 void AbsIntInstructionHandler::SetReg(int regIdx, Type type)
92 {
93 SetReg(regIdx, MkVal(type));
94 }
95
SetRegAndOthersOfSameOrigin(int regIdx,const AbstractTypedValue & val)96 void AbsIntInstructionHandler::SetRegAndOthersOfSameOrigin(int regIdx, const AbstractTypedValue &val)
97 {
98 context_.ExecCtx().CurrentRegContext().ChangeValuesOfSameOrigin(regIdx, val);
99 }
100
SetRegAndOthersOfSameOrigin(int regIdx,Type type)101 void AbsIntInstructionHandler::SetRegAndOthersOfSameOrigin(int regIdx, Type type)
102 {
103 SetRegAndOthersOfSameOrigin(regIdx, MkVal(type));
104 }
105
GetAcc()106 const AbstractTypedValue &AbsIntInstructionHandler::GetAcc()
107 {
108 return context_.ExecCtx().CurrentRegContext()[ACC];
109 }
110
GetAccType()111 Type AbsIntInstructionHandler::GetAccType()
112 {
113 return GetAcc().GetAbstractType();
114 }
115
SetAcc(const AbstractTypedValue & val)116 void AbsIntInstructionHandler::SetAcc(const AbstractTypedValue &val)
117 {
118 SetReg(ACC, val);
119 }
120
SetAcc(Type type)121 void AbsIntInstructionHandler::SetAcc(Type type)
122 {
123 SetReg(ACC, type);
124 }
125
SetAccAndOthersOfSameOrigin(const AbstractTypedValue & val)126 void AbsIntInstructionHandler::SetAccAndOthersOfSameOrigin(const AbstractTypedValue &val)
127 {
128 SetRegAndOthersOfSameOrigin(ACC, val);
129 }
130
SetAccAndOthersOfSameOrigin(Type type)131 void AbsIntInstructionHandler::SetAccAndOthersOfSameOrigin(Type type)
132 {
133 SetRegAndOthersOfSameOrigin(ACC, type);
134 }
135
MkVal(Type t)136 AbstractTypedValue AbsIntInstructionHandler::MkVal(Type t)
137 {
138 return AbstractTypedValue {t, context_.NewVar(), GetInst()};
139 }
140
TypeOfClass(Class const * klass)141 Type AbsIntInstructionHandler::TypeOfClass(Class const *klass)
142 {
143 return Type {klass};
144 }
145
ReturnType()146 Type AbsIntInstructionHandler::ReturnType()
147 {
148 return context_.ReturnType();
149 }
150
ExecCtx()151 ExecContext &AbsIntInstructionHandler::ExecCtx()
152 {
153 return context_.ExecCtx();
154 }
155
DumpRegs(const RegContext & ctx)156 void AbsIntInstructionHandler::DumpRegs(const RegContext &ctx)
157 {
158 LOG_VERIFIER_DEBUG_REGISTERS("registers =", ctx.DumpRegs(GetTypeSystem()));
159 }
160
Sync()161 void AbsIntInstructionHandler::Sync()
162 {
163 auto addr = inst_.GetAddress();
164 ExecContext &execCtx = ExecCtx();
165 // NOTE(vdyadov): add verification options to show current context and contexts diff in case of incompatibility
166 #ifndef NDEBUG
167 execCtx.StoreCurrentRegContextForAddr(
168 addr, [this, printHdr = true](int regIdx, const auto &src, const auto &dst) mutable {
169 if (printHdr) {
170 LOG_VERIFIER_REGISTER_CONFLICT_HEADER();
171 printHdr = false;
172 }
173 LOG_VERIFIER_REGISTER_CONFLICT(RegisterName(regIdx), ToString(src.GetAbstractType()),
174 ToString(dst.GetAbstractType()));
175 return true;
176 });
177 #else
178 execCtx.StoreCurrentRegContextForAddr(addr);
179 #endif
180 }
181
182 } // namespace ark::verifier
183