• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1### 本 cookbook 的主要目标是为主要支持的功能提供使用示例,帮助开发者快速开始使用 LibAbcKit API。
2
3## 获取 API 实现
4
5```cpp
6enum AbckitApiVersion version = ABCKIT_VERSION_RELEASE_1_0_0;
7auto impl = AbckitGetApiImpl(version);                 // 顶级 API,包含入口点
8auto implI = AbckitGetInspectApiImpl(version);         // 语言无关的检查 API
9auto implM = AbckitGetModifyApiImpl(version);          // 语言无关的修改 API
10auto implArkI = AbckitGetArkTSInspectApiImpl(version); // 语言相关的检查 API
11auto implArkM = AbckitGetArkTSModifyApiImpl(version);  // 语言相关的修改 API
12
13auto implG = AbckitGetGraphApiImpl(version);           // 语言无关的图 API
14auto dynG = AbckitGetIsaApiDynamicImpl(version);       // 语言相关的图 API
15auto statG = AbckitGetIsaApiStaticImpl(version);       // 语言相关的图 API
16```
17
18在 .cpp 文件开头为每个 API 创建一个静态实例即可
19
20## 错误处理
21
22libabckit 中的 API 在执行后都会设置错误值。您可以使用 `impl->getLastError()` 获取它。如果没有错误,返回值将是 ABCKIT_STATUSNO_ERROR。
23使用以下方式检查执行状态:
24
25```cpp
26assert(impl->getLastError() == ABCKIT_STATUSNO_ERROR);
27```
28
29## LibAbcKit 中的字符串
30
31以下是 libabckit 中处理字符串的自定义函数的有用示例:
32
33```cpp
34AbckitString *str = implI->createString(file, "new_string", strlen("new_string"));
35
36std::string AbckitStringToString(AbckitFile *file, AbckitString *str)
37{
38    std::size_t len = 0;
39    implI->abckitStringToString(file, str, nullptr, &len);
40    auto name = malloc(len + 1);
41    implI->abckitStringToString(file, str, name, &len);
42    std::string res {name};
43    free(name);
44
45    return res;
46}
47```
48
49# 元数据
50
51## 打开/关闭/写入
52
53### _打开文件_
54
55该接口是初始化的唯一入口,必须首先调用。
56
57```cpp
58AbckitFile *file = implI->openAbc(path_to_abc, path_to_abc_length);
59```
60
61文件处理完成后,调用 WriteAbc() 或 CloseFile() 函数,以防止内存泄漏。
62
63### _写入/关闭_
64
65```cpp
66impl->writeAbc(file, path_to_output_file, path_to_output_file_length); // 保存更改并关闭
67// 或者
68impl->closeFile(file); // 关闭而不保存更改
69```
70
71## 遍历
72
73libabckit 对象的层次结构:
74
751. 文件包含模块("文件"是 ".abc 文件","模块"是"源代码文件"的抽象)
762. 模块包含:命名空间、顶级类和顶级函数
773. 命名空间包含:嵌套命名空间、类和函数
784. 类包含函数(方法)
795. 函数包含嵌套函数
80
81<!-- file module  class  function -> introduce hierarchy -->
82
83libabckit 中的所有枚举器都接受 libabckit 对象、用户数据的 void* 指针和回调 lambda:
84
85```cpp
86void XXXEnumerateYYY(AbckitCoreXXX* xxx, void *data, bool(*cb)(AbckitCoreYYY* yyy, void *data))
87```
88
89### _枚举类中的方法_
90
91```cpp
92// AbckitCoreClass *klass
93implI->classEnumerateMethods(klass, data, [](AbckitCoreMethod *method, void *data) {
94    return true;
95});
96```
97
98### _收集模块中的所有顶级类_
99
100```cpp
101// AbckitCoreModule *module
102std::vector<AbckitCoreClass *> classes;
103implI->moduleEnumerateClasses(module, (void*)&classes, [](AbckitCoreClass *klass, void *data) {
104    ((std::vector<AbckitCoreClass*>*)data)->emplace.back(klass);
105    return true;
106});
107```
108
109## 检查
110
111### _获取方法的父类_
112
113```cpp
114// AbckitCoreMethod *method
115AbckitCoreClass *klass = implI->functionGetParentClass(method);
116```
117
118### _获取值_
119
120<!-- Test: LiteralGetU32_2 -->
121
122```cpp
123// AbckitLiteral *res
124void GetValues(AbckitValue *u32_res, AbckitValue *double_res, AbckitValue *string_res) {
125    uint32_t val = implI->literalGetU32(u32_res);
126    double d = implI->valueGetDouble(double_res);
127    AbckitString *s = implI->valueGetString(string_res);
128}
129```
130
131### _获取模块名称_
132
133```cpp
134// AbckitCoreModule *mod
135AbckitString *GetModuleName(AbckitCoreModule *mod) {
136    return implI->moduleGetName(mod);
137}
138```
139
140## 元数据语言 API
141
142### _为 ArkTS 方法添加注解_
143
144```cpp
145void AddAnno(AbckitModifyContext *file, AbckitCoreMethod *method) {
146    auto mod = implI->functionGetModule(method);
147
148    // 查找名称为 "Anno" 的注解接口
149    AbckitCoreAnnotationInterface *ai;
150    implI->moduleEnumerateAnnotationInterfaces(mod, &ai, [](AbckitCoreAnnotationInterface *annoI, void *data) {
151        auto ai1 = (AbckitCoreAnnotationInterface **)data;
152        auto file = implI->annotationInterfaceGetInspectContext(annoI);
153        auto str = implI->annotationInterfaceGetName(annoI);
154        auto name = AbckitStringToString(file, str);
155        if (name == "Anno") {
156            (*ai1) = annoI;
157        }
158        return true;
159    });
160
161    // 为方法添加 "@Anno" 注解
162    struct AbckitArktsAnnotationCreateParams annoCreateParams;
163    annoCreateParams.ai = implArkI->coreAnnotationInterfaceToArkTsAnnotationInterface(ai);
164    AbckitArktsAnnotation *anno = implArkM->functionAddAnnotation(file,
165        implArkI->coreFunctionToArkTsFunction(method), &annoCreateParams);
166}
167```
168
169### _转换 AbckitArtksXXX -> AbckitXXX / AbckitXXX -> AbckitArktsXXX_
170
171```cpp
172AbckitCoreModule *CastToAbcKit(AbckitArktsInspectApi implArkI, AbckitArktsModule *mod) {
173    return implArkI->arkTsModuleToCoreModule(mod); }
174
175AbckitArktsAnnotation *CastToArkTS(AbckitArktsInspectApi implArkI, AbckitCoreAnnotation *anno) {
176    return implArkI->coreAnnotationToArkTsAnnotation(anno); }
177```
178
179## 修改
180
181### _创建值_
182
183```cpp
184AbckitLiteral *res1 = implM->createLiteralString(file, "asdf");
185AbckitLiteral *res2 = implM->createLiteralDouble(file, 1.0);
186AbckitLiteral *res = implM->createLiteralU32(file, 1);
187```
188
189```cpp
190AbckitValue *res_u = implM->createValueU1(file, true);
191AbckitValue *res_d = implM->createValueDouble(file, 1.2);
192```
193
194### _获取值类型_
195
196<!-- Test: ValueGetType_1 -->
197
198```cpp
199AbckitType *s_type = implI->valueGetType(res_s); // val_s->id == ABCKIT_TYPE_ID_STRING
200AbckitType *u_type = implI->valueGetType(res_u); // val_u->id == ABCKIT_TYPE_ID_U1
201AbckitType *d_type = implI->valueGetType(res_d); // val_d->id == ABCKIT_TYPE_ID_F32,
202```
203
204# 图
205
206## _创建和销毁图_
207
208```cpp
209AbckitGraph *graph = implI->createGraphFromFunction(method);
210// ...
211impl->destroyGraph(graph);
212```
213
214## _图遍历_
215
216```cpp
217implG->gVisitBlocksRpo(ctxG, &bbs, [](AbckitBasicBlock *bb, void *data) {
218    // 用户 lambda
219});
220```
221
222```cpp
223implG->bbVisitSuccBlocks(bb, &succBBs, [](AbckitBasicBlock *succBasicBlock, void *d) {
224    // 用户 lambda
225});
226```
227
228```cpp
229implG->bbVisitPredBlocks(bb, &predBBs,
230    [](AbckitBasicBlock *succBasicBlock, void *d) {
231        // 用户 lambda
232    });
233
234// ...
235```
236
237### _收集图中的所有基本块_
238
239```cpp
240std::vector<AbckitBasicBlock *> bbs;
241implG->gVisitBlocksRPO(ctxG, &bbs, [](AbckitBasicBlock *bb, void *data) {
242    ((std::vector<AbckitBasicBlock *> *)data)->emplace_back(bb);
243});
244```
245
246### _收集基本块中的所有指令_
247
248```cpp
249std::vector<AbckitInst *> insts;
250for (auto *inst = implG->bbGetFirstInst(bb); inst != nullptr; inst = implG->iGetNext(inst)) {
251    insts.emplace_back(inst);
252}
253```
254
255### _收集块的后继_
256
257```cpp
258std::vector<AbckitBasicBlock *> succBBs;
259implG->bbVisitSuccBlocks(bb, &succBBs,
260    [](AbckitBasicBlock *succBasicBlock, void *d) {
261        auto *succs = (std::vector<AbckitBasicBlock *> *)d;
262        succs->emplace_back(succBasicBlock);
263    });
264```
265
266## 图检查
267
268### _获取方法_
269
270```cpp
271AbckitCoreMethod *method = implG->iGetFunction(curInst);
272```
273
274## 图修改
275
276### _创建基本块_
277
278```cpp
279AbckitBasicBlock *empty = implG->bbCreateEmpty(ctxG);
280```
281
282### _使用常量创建指令_
283
284```cpp
285AbckitInst *new_inst = implG->gFindOrCreateConstantI64(ctxG, 1U);
286```
287
288### _连接和断开块_
289
290<!-- Test: BBcreateEmptyBlock_1 -->
291
292```cpp
293auto *start = implG->gGetStartBasicBlock(ctxG);
294auto *bb = implG->bbCreateEmpty(ctxG);
295
296implG->bbInsertSuccBlock(start, bb, 0);
297implG->bbDisconnectSuccBlock(start, 0);
298```
299
300### _插入指令_
301
302```cpp
303implG->bbAddInstBack(bb, some_inst_1);
304implG->iInsertAfter(some_inst_1, some_inst_2);
305```
306
307## 图语言
308
309### _创建指令_
310
311```cpp
312// 用于静态
313AbckitInst *neg_inst = statG->iCreateNeg(ctxG, new_inst);
314AbckitInst *add_inst = statG->iCreateAdd(ctxG, neg_inst, new_inst);
315AbckitInst *ret = statG->iCreateReturnVoid(ctxG);
316
317// 用于动态
318AbckitInst *neg_inst = dynG->iCreateNeg(ctxG, new_inst);
319AbckitInst *add_inst = dynG->iCreateAdd2(ctxG, neg_inst, new_inst);
320AbckitInst *ret = dynG->iCreateReturnundefined(ctxG);
321```
322
323### _为 ArkTS 创建 'print("Hello")'_
324
325```cpp
326AbckitInst *str = dynG->iCreateLoadString(ctxG, implM->createString(file, "Hello", strlen("Hello")));
327AbckitInst *print = dynG->iCreateTryldglobalbyname(ctxG, implM->createString(file, "print", strlen("print")));
328AbckitInst *callArg = dynG->iCreateCallarg1(ctxG, print, str);
329```
330
331# 用户场景
332
333### _枚举模块中方法的名称_
334
335```cpp
336std::vector<std::string> functionNames;
337
338std::function<void(AbckitCoreFunction *)> cbFunc = [&](AbckitCoreFunction *f) {
339    auto funcName = helpers::AbckitStringToString(implI->functionGetName(f));
340    functionNames.emplace_back(funcName);
341};
342
343std::function<void(AbckitCoreClass *)> cbClass = [&](AbckitCoreClass *c) {
344    implI->classEnumerateMethods(c, &cbFunc, [](AbckitCoreFunction *m, void *cb) {
345        (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(m);
346        return true;
347    });
348};
349
350std::function<void(AbckitCoreNamespace *)> cbNamespace;
351cbNamespace = [&](AbckitCoreNamespace *n) {
352    implI->namespaceEnumerateNamespaces(n, &cbNamespace, [](AbckitCoreNamespace *n, void *cb) {
353        (*reinterpret_cast<std::function<void(AbckitCoreNamespace *)> *>(cb))(n);
354        return true;
355    });
356    implI->namespaceEnumerateClasses(n, &cbClass, [](AbckitCoreClass *c, void *cb) {
357        (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
358        return true;
359    });
360    implI->namespaceEnumerateTopLevelFunctions(n, &cbFunc, [](AbckitCoreFunction *f, void *cb) {
361        (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(f);
362        return true;
363    });
364};
365
366std::function<void(AbckitCoreModule *)> cbModule = [&](AbckitCoreModule *m) {
367    implI->moduleEnumerateNamespaces(m, &cbNamespace, [](AbckitCoreNamespace *n, void *cb) {
368        (*reinterpret_cast<std::function<void(AbckitCoreNamespace *)> *>(cb))(n);
369        return true;
370    });
371    implI->moduleEnumerateClasses(m, &cbClass, [](AbckitCoreClass *c, void *cb) {
372        (*reinterpret_cast<std::function<void(AbckitCoreClass *)> *>(cb))(c);
373        return true;
374    });
375    implI->moduleEnumerateTopLevelFunctions(m, &cbFunc, [](AbckitCoreFunction *m, void *cb) {
376        (*reinterpret_cast<std::function<void(AbckitCoreFunction *)> *>(cb))(m);
377        return true;
378    });
379};
380
381implI->fileEnumerateModules(file, &cbModule, [](AbckitCoreModule *m, void *cb) {
382    (*reinterpret_cast<std::function<void(AbckitCoreModule *)> *>(cb))(m);
383    return true;
384});
385```
386
387### _收集前驱基本块_
388
389```cpp
390std::vector<AbckitBasicBlock *> predBBs;
391implG->bbVisitPredBlocks(bb, &predBBs,
392    [](AbckitBasicBlock *succBasicBlock, void *d) {
393    auto *preds = (std::vector<AbckitBasicBlock *> *)d;
394    preds->emplace_back(succBasicBlock);
395    });
396```