• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "api_modifier.h"
17 #include "helpers/visit_helper/visit_helper-inl.h"
18 #include "libabckit/include/c/metadata_core.h"
19 
20 #include <iostream>
21 #include <cstring>
22 
Run()23 void ApiModifier::Run()
24 {
25     visitor_.EnumerateModules([&](AbckitCoreModule *mod) {
26         AbckitCoreImportDescriptor *impDescriptor = GetImportDescriptor(mod);
27         if (impDescriptor == nullptr) {
28             return;
29         }
30         visitor_.EnumerateModuleFunctions(mod, [&](AbckitCoreFunction *method) {
31             ModifyFunction(method, impDescriptor);
32             return true;
33         });
34     });
35 }
36 
GetImportDescriptor(AbckitCoreModule * module)37 AbckitCoreImportDescriptor *ApiModifier::GetImportDescriptor(AbckitCoreModule *module)
38 {
39     AbckitCoreImportDescriptor *impDescriptor = nullptr;
40     visitor_.EnumerateModuleImports(module, [&](AbckitCoreImportDescriptor *id) {
41         auto importName = visitor_.GetString(implI_->importDescriptorGetName(id));
42         auto *importedModule = implI_->importDescriptorGetImportedModule(id);
43         auto source = visitor_.GetString(implI_->moduleGetName(importedModule));
44         if (source != methodInfo_.path) {
45             return false;
46         }
47         if (importName == methodInfo_.className) {
48             impDescriptor = id;
49             return true;
50         }
51         return false;
52     });
53     return impDescriptor;
54 }
55 
ModifyFunction(AbckitCoreFunction * method,AbckitCoreImportDescriptor * id)56 void ApiModifier::ModifyFunction(AbckitCoreFunction *method, AbckitCoreImportDescriptor *id)
57 {
58     visitor_.EnumerateFunctionInsts(method, [&](AbckitInst *inst) {
59         auto subclassMethod = GetSubclassMethod(id, inst);
60         if (subclassMethod != nullptr) {
61             AddParamChecker(subclassMethod);
62         }
63     });
64 }
65 
GetSubclassMethod(AbckitCoreImportDescriptor * id,AbckitInst * inst)66 AbckitCoreFunction *ApiModifier::GetSubclassMethod(AbckitCoreImportDescriptor *id, AbckitInst *inst)
67 {
68     if (dynG_->iGetOpcode(inst) != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR) {
69         return nullptr;
70     }
71 
72     if (dynG_->iGetImportDescriptor(inst) != id) {
73         return nullptr;
74     }
75 
76     AbckitCoreFunction *foundMethod = nullptr;
77     visitor_.EnumerateInstUsers(inst, [&](AbckitInst *user) {
78         if (dynG_->iGetOpcode(user) == ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINECLASSWITHBUFFER) {
79             auto method = implG_->iGetFunction(user);
80             auto klass = implI_->functionGetParentClass(method);
81             foundMethod = GetMethodToModify(klass);
82         }
83     });
84 
85     return foundMethod;
86 }
87 
GetMethodToModify(AbckitCoreClass * klass)88 AbckitCoreFunction *ApiModifier::GetMethodToModify(AbckitCoreClass *klass)
89 {
90     AbckitCoreFunction *foundMethod = nullptr;
91     visitor_.EnumerateClassMethods(klass, [&](AbckitCoreFunction *method) {
92         auto name = visitor_.GetString(implI_->functionGetName(method));
93         if (name == methodInfo_.methodName) {
94             foundMethod = method;
95             return true;
96         }
97         return false;
98     });
99     return foundMethod;
100 }
101 
AddParamChecker(AbckitCoreFunction * method)102 void ApiModifier::AddParamChecker(AbckitCoreFunction *method)
103 {
104     AbckitGraph *graph = implI_->createGraphFromFunction(method);
105 
106     visitor_.TransformMethod(method, [&](AbckitFile *file, AbckitCoreFunction *method) {
107         AbckitBasicBlock *startBB = implG_->gGetStartBasicBlock(graph);
108         AbckitInst *idx = implG_->bbGetLastInst(startBB);
109         AbckitInst *arr = implG_->iGetPrev(idx);
110 
111         std::vector<AbckitBasicBlock *> succBBs;
112         implG_->bbVisitSuccBlocks(startBB, &succBBs, [](AbckitBasicBlock *succBasicBlock, void *d) {
113             auto *succs = reinterpret_cast<std::vector<AbckitBasicBlock *> *>(d);
114             succs->emplace_back(succBasicBlock);
115             return true;
116         });
117 
118         AbckitString *str = implM_->createString(file, "length", strlen("length"));
119 
120         AbckitInst *constant = implG_->gFindOrCreateConstantI32(graph, -1);
121         AbckitInst *arrLength = dynG_->iCreateLdobjbyname(graph, arr, str);
122 
123         AbckitBasicBlock *trueBB = succBBs[0];
124         implG_->bbDisconnectSuccBlock(startBB, ABCKIT_TRUE_SUCC_IDX);
125         AbckitBasicBlock *falseBB = implG_->bbCreateEmpty(graph);
126         implG_->bbAppendSuccBlock(falseBB, implG_->gGetEndBasicBlock(graph));
127         implG_->bbAddInstBack(falseBB, dynG_->iCreateReturn(graph, constant));
128         AbckitBasicBlock *ifBB = implG_->bbCreateEmpty(graph);
129         AbckitInst *intrinsicGreatereq = dynG_->iCreateGreatereq(graph, arrLength, idx);
130         AbckitInst *ifInst = dynG_->iCreateIf(graph, intrinsicGreatereq, ABCKIT_ISA_API_DYNAMIC_CONDITION_CODE_CC_EQ);
131         implG_->bbAddInstBack(ifBB, arrLength);
132         implG_->bbAddInstBack(ifBB, intrinsicGreatereq);
133         implG_->bbAddInstBack(ifBB, ifInst);
134         implG_->bbAppendSuccBlock(startBB, ifBB);
135         implG_->bbAppendSuccBlock(ifBB, trueBB);
136         implG_->bbAppendSuccBlock(ifBB, falseBB);
137 
138         implM_->functionSetGraph(method, graph);
139         impl_->destroyGraph(graph);
140     });
141 }
142