1 /*
2 * Copyright (c) 2023 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 "verify_annotation.h"
17 #include "global_tables.h"
18 #include "reflection_analysis.h"
19
20 namespace maple {
21 namespace verifyanno {
22 constexpr char kDeferredThrowVerifyError[] = "Lcom_2Fhuawei_2Fark_2Fannotation_2Fverify_2FVerfAnnoThrowVerifyError_3B";
23 constexpr char kDeferredExtendFinalCheck[] =
24 "Lcom_2Fhuawei_2Fark_2Fannotation_2Fverify_2FVerfAnnoDeferredExtendFinalCheck_3B";
25 constexpr char kDeferredOverrideFinalCheck[] =
26 "Lcom_2Fhuawei_2Fark_2Fannotation_2Fverify_2FVerfAnnoDeferredOverrideFinalCheck_3B";
27 constexpr char kDeferredAssignableCheck[] =
28 "Lcom_2Fhuawei_2Fark_2Fannotation_2Fverify_2FVerfAnnoDeferredAssignableCheck_3B";
29 constexpr char kAssignableChecksContainer[] =
30 "Lcom_2Fhuawei_2Fark_2Fannotation_2Fverify_2FVerfAnnoDeferredAssignableChecks_3B";
31 } // namespace verifyanno
32
SimplifyClassName(const std::string & name)33 inline std::string SimplifyClassName(const std::string &name)
34 {
35 const std::string postFix = "_3B";
36 if (name.rfind(postFix) == (name.size() - postFix.size())) {
37 std::string shortName = name.substr(0, name.size() - postFix.size());
38 return shortName.append(";");
39 }
40 return name;
41 }
42
GetOrCreateStructType(const std::string & name,MIRModule & md)43 inline MIRStructType *GetOrCreateStructType(const std::string &name, MIRModule &md)
44 {
45 return static_cast<MIRStructType *>(GlobalTables::GetTypeTable().GetOrCreateClassType(name, md));
46 }
47
NewAnnotationElement(MIRModule & md,const GStrIdx & nameIdx,PragmaValueType type)48 MIRPragmaElement *NewAnnotationElement(MIRModule &md, const GStrIdx &nameIdx, PragmaValueType type)
49 {
50 auto *elem = md.GetMemPool()->New<MIRPragmaElement>(md.GetMPAllocator());
51 elem->SetType(type);
52 elem->SetNameStrIdx(nameIdx);
53 return elem;
54 }
55
NewAnnotationElement(MIRModule & md,const std::string & name,PragmaValueType type)56 MIRPragmaElement *NewAnnotationElement(MIRModule &md, const std::string &name, PragmaValueType type)
57 {
58 GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name);
59 return NewAnnotationElement(md, nameIdx, type);
60 }
61
NewAnnotationStringElement(MIRModule & md,const std::string & name,const std::string & value)62 MIRPragmaElement *NewAnnotationStringElement(MIRModule &md, const std::string &name, const std::string &value)
63 {
64 MIRPragmaElement *elem = NewAnnotationElement(md, name, kValueString);
65 if (!value.empty()) {
66 elem->SetU64Val(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(value).GetIdx());
67 }
68 return elem;
69 }
70
NewPragmaRTAnnotation(MIRModule & md,const MIRStructType & clsType,const MIRStructType & aType,PragmaKind kind)71 MIRPragma *NewPragmaRTAnnotation(MIRModule &md, const MIRStructType &clsType, const MIRStructType &aType,
72 PragmaKind kind)
73 {
74 auto *pragma = md.GetMemPool()->New<MIRPragma>(md, md.GetMPAllocator());
75 pragma->SetStrIdx(clsType.GetNameStrIdx());
76 pragma->SetTyIdx(aType.GetTypeIndex());
77 pragma->SetKind(kind);
78 pragma->SetVisibility(kVisRuntime);
79 return pragma;
80 }
81
NewPragmaRTClassAnnotation(MIRModule & md,const MIRStructType & clsType,const std::string & aTypeName)82 MIRPragma *NewPragmaRTClassAnnotation(MIRModule &md, const MIRStructType &clsType, const std::string &aTypeName)
83 {
84 MIRStructType *aType = GetOrCreateStructType(aTypeName, md);
85 return NewPragmaRTAnnotation(md, clsType, *aType, kPragmaClass);
86 }
87
88 // creates pragma not inserted into clsType pragmaVec
NewAssignableCheckAnno(MIRModule & md,const MIRStructType & clsType,const AssignableCheckPragma & info)89 MIRPragma *NewAssignableCheckAnno(MIRModule &md, const MIRStructType &clsType, const AssignableCheckPragma &info)
90 {
91 MIRPragma *pr = NewPragmaRTClassAnnotation(md, clsType, verifyanno::kDeferredAssignableCheck);
92 pr->PushElementVector(NewAnnotationStringElement(md, "dst", SimplifyClassName(info.GetToType())));
93 pr->PushElementVector(NewAnnotationStringElement(md, "src", SimplifyClassName(info.GetFromType())));
94 return pr;
95 }
96
AddVerfAnnoThrowVerifyError(MIRModule & md,const ThrowVerifyErrorPragma & info,MIRStructType & clsType)97 void AddVerfAnnoThrowVerifyError(MIRModule &md, const ThrowVerifyErrorPragma &info, MIRStructType &clsType)
98 {
99 const auto &pragmaVec = clsType.GetPragmaVec();
100 for (auto pragmaPtr : pragmaVec) {
101 if (pragmaPtr == nullptr) {
102 continue;
103 }
104 MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pragmaPtr->GetTyIdx());
105 if (mirType != nullptr && mirType->GetName().compare(verifyanno::kDeferredThrowVerifyError) == 0) {
106 return;
107 }
108 }
109 MIRPragma *pr = NewPragmaRTClassAnnotation(md, clsType, verifyanno::kDeferredThrowVerifyError);
110 pr->PushElementVector(NewAnnotationStringElement(md, "msg", info.GetMessage()));
111 clsType.PushbackPragma(pr);
112 }
113
AddVerfAnnoAssignableCheck(MIRModule & md,std::vector<const AssignableCheckPragma * > & info,MIRStructType & clsType)114 void AddVerfAnnoAssignableCheck(MIRModule &md, std::vector<const AssignableCheckPragma *> &info, MIRStructType &clsType)
115 {
116 if (info.empty()) {
117 return;
118 }
119
120 if (info.size() == 1) {
121 MIRPragma *pr = NewAssignableCheckAnno(md, clsType, *info.front());
122 clsType.PushbackPragma(pr);
123 return;
124 }
125
126 // container pragma
127 MIRPragma *prContainer = NewPragmaRTClassAnnotation(md, clsType, verifyanno::kAssignableChecksContainer);
128 MIRPragmaElement *elemContainer = NewAnnotationElement(md, "value", kValueArray);
129
130 GStrIdx singleAnnoTypeName =
131 GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(verifyanno::kDeferredAssignableCheck);
132 for (auto *singleInfo : info) {
133 MIRPragmaElement *elem = NewAnnotationElement(md, singleAnnoTypeName, kValueAnnotation);
134 elem->SetTypeStrIdx(singleAnnoTypeName);
135 elem->SubElemVecPushBack(NewAnnotationStringElement(md, "dst", SimplifyClassName(singleInfo->GetToType())));
136 elem->SubElemVecPushBack(NewAnnotationStringElement(md, "src", SimplifyClassName(singleInfo->GetFromType())));
137 elemContainer->SubElemVecPushBack(elem);
138 }
139
140 prContainer->PushElementVector(elemContainer);
141 clsType.PushbackPragma(prContainer);
142 }
143
AddVerfAnnoExtendFinalCheck(MIRModule & md,MIRStructType & clsType)144 void AddVerfAnnoExtendFinalCheck(MIRModule &md, MIRStructType &clsType)
145 {
146 MIRPragma *pr = NewPragmaRTClassAnnotation(md, clsType, verifyanno::kDeferredExtendFinalCheck);
147 clsType.PushbackPragma(pr);
148 }
149
AddVerfAnnoOverrideFinalCheck(MIRModule & md,MIRStructType & clsType)150 void AddVerfAnnoOverrideFinalCheck(MIRModule &md, MIRStructType &clsType)
151 {
152 MIRPragma *pr = NewPragmaRTClassAnnotation(md, clsType, verifyanno::kDeferredOverrideFinalCheck);
153 clsType.PushbackPragma(pr);
154 }
155 } // namespace maple
156