• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1### The main goals of this cookbook are to provide recipes for the main supported functions and to help you quickly get started with the LibAbcKit API.
2
3## Get API implementations
4
5```cpp
6enum AbckitApiVersion version = ABCKIT_VERSION_RELEASE_1_0_0;
7auto impl = AbckitGetApiImpl(version); // top level api with entry points
8auto implI = AbckitGetInspectApiImpl(version); // language-independent inspect api
9auto implM = AbckitGetModifyApiImpl(version); // language-independent modify api
10auto implArkI = AbckitGetArkTSInspectApiImpl(version); // language-dependent inspect api
11auto implArkM = AbckitGetArkTSModifyApiImpl(version); // language-dependent modify api
12
13auto implG = AbckitGetGraphApiImpl(version); // language-independent graph api
14auto dynG = AbckitGetIsaApiDynamicImpl(version); // language-dependent graph api
15auto statG = AbckitGetIsaApiStaticImpl(version); // language-dependent graph api
16```
17
18One static instance of each at the beginning of the .cpp file is enough
19
20## Errors
21
22Every API in libabckit sets error value after execution. You can get it with `impl->getLastError()`. If there are no errors, the return value will be ABCKIT_STATUSNO_ERROR.
23Сheck the execution status with:
24
25```cpp
26assert(impl->getLastError() == ABCKIT_STATUSNO_ERROR);
27```
28
29## Strings in LibAbcKit
30
31Here is an useful example of a custom function for working with strings in libabckit:
32
33```cpp
34AbckitString *str = implI->createString(file, "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# Metadata
50
51## Open/Close/Write
52
53### _Open file_
54
55Mandatory and only entry point
56
57```cpp
58AbckitFile *file = implI->openAbc(path_to_abc);
59```
60
61Make sure that you have used the WriteAbc() or CloseFile() function after working with the file. This way you will avoid memory leaks
62
63### _Write or Close_
64
65```cpp
66impl->writeAbc(file, path_to_output_file); // save changes and close
67// or
68impl->closeFile(file); // close without saving changes
69```
70
71## Traversing
72
73libabckit objects hierarchy:
74
751. file contains modules ("file" is ".abc file" and "module" is the abstract of "source code file")
762. module contains: namespaces, top level classes, top level functions
773. namespace contains: nested namespaces, classes, functions
784. class contains: functions (methods)
795. functions contains: nested functions
80
81<!-- file module  class  function -> introduce hierarchy -->
82
83All the enumerators in libabckit accepts libabckit object, void\* data with user data and callback lambda:
84
85```cpp
86void XXXEnumerateYYY(AbckitCoreXXX* xxx, void *data, bool(*cb)(AbckitCoreYYY* yyy, void *data))
87```
88
89### _Enumerate methods from class_
90
91```cpp
92// AbckitCoreClass *klass
93implI->classEnumerateMethods(klass, data, [](AbckitCoreMethod *method, void *data) {
94    return true;
95});
96```
97
98### _Collect all top level classes from module_
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## Inspecting
110
111### _Get method's parent class_
112
113```cpp
114// AbckitCoreMethod *method
115AbckitCoreClass *klass = implI->functionGetParentClass(method);
116```
117
118### _Get value_
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### _Get module name_
132
133```cpp
134// AbckitCoreModule *mod
135AbckitString *GetModuleName(AbckitCoreModule *mod) {
136    return implI->moduleGetName(mod);
137}
138```
139
140## Metadata Lang API
141
142### _Add annotation for arkts method_
143
144```cpp
145void AddAnno(AbckitModifyContext *file, AbckitCoreMethod *method) {
146    auto mod = implI->functionGetModule(method);
147
148    // Find annoation interface with name "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    // Add "@Anno" annotation for method
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### _Cast 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## Modification
180
181### _Create values_
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### _Get value type_
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# Graph
205
206## _Create and destroy graph_
207
208```cpp
209AbckitGraph *graph = implI->createGraphFromFunction(method);
210// ...
211impl->destroyGraph(graph);
212```
213
214## _Graph traversal_
215
216```cpp
217implG->gVisitBlocksRpo(ctxG, &bbs, [](AbckitBasicBlock *bb, void *data) {
218    // user lambda
219});
220```
221
222```cpp
223implG->bbVisitSuccBlocks(bb, &succBBs, [](AbckitBasicBlock *succBasicBlock, void *d) {
224    // user lambda
225});
226```
227
228```cpp
229implG->bbVisitPredBlocks(bb, &predBBs,
230    [](AbckitBasicBlock *succBasicBlock, void *d) {
231        // user lambda
232    });
233
234// ...
235```
236
237### _Collect all basic blocks from graph_
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### _Collect all inst in basic block_
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### _Collect block's succs_
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## Graph inspecting
267
268### _Get method_
269
270```cpp
271AbckitCoreMethod *method = implG->iGetFunction(curInst);
272```
273
274## Graph modification
275
276### _Create basic block_
277
278```cpp
279AbckitBasicBlock *empty = implG->bbCreateEmpty(ctxG);
280```
281
282### _Create insts with const_
283
284```cpp
285AbckitInst *new_inst = implG->gFindOrCreateConstantI64(ctxG, 1U);
286```
287
288### _Connect and disconnect blocks_
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### _Insert instructions_
301
302```cpp
303implG->bbAddInstBack(bb, some_inst_1);
304implG->iInsertAfter(some_inst_1, some_inst_2);
305```
306
307## Graph-lang
308
309### _Create instructions_
310
311```cpp
312// for static
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// for dynamic
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### _Create 'print("Hello")' for ArkTS1.0_
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# User scenarios
332
333### _Enumerate the names of methods from the module_
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### _Collect predecessor basic blocks_
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```
397