• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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