1/*===-- module.c - tool for testing libLLVM and llvm-c API ----------------===*\
2|* *|
3|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
4|* Exceptions. *|
5|* See https://llvm.org/LICENSE.txt for license information. *|
6|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
7|* *|
8|*===----------------------------------------------------------------------===*|
9|* *|
10|* This file implements the --module-dump, --module-list-functions and *|
11|* --module-list-globals commands in llvm-c-test. *|
12|* *|
13\*===----------------------------------------------------------------------===*/
14
15#include "llvm-c-test.h"
16#include "llvm-c/BitReader.h"
17#include <stdio.h>
18#include <stdlib.h>
19
20static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) {
21 char *CErr = LLVMGetDiagInfoDescription(DI);
22 fprintf(stderr, format: "Error with new bitcode parser: %s\n", CErr);
23 LLVMDisposeMessage(Message: CErr);
24 exit(status: 1);
25}
26
27LLVMModuleRef llvm_load_module(LLVMContextRef C, bool Lazy, bool New) {
28 LLVMMemoryBufferRef MB;
29 LLVMModuleRef M;
30 char *msg = NULL;
31
32 if (LLVMCreateMemoryBufferWithSTDIN(OutMemBuf: &MB, OutMessage: &msg)) {
33 fprintf(stderr, format: "Error reading file: %s\n", msg);
34 exit(status: 1);
35 }
36
37 LLVMBool Ret;
38 if (New) {
39 LLVMContextSetDiagnosticHandler(C, Handler: diagnosticHandler, NULL);
40 if (Lazy)
41 Ret = LLVMGetBitcodeModuleInContext2(ContextRef: C, MemBuf: MB, OutM: &M);
42 else
43 Ret = LLVMParseBitcodeInContext2(ContextRef: C, MemBuf: MB, OutModule: &M);
44 } else {
45 if (Lazy)
46 Ret = LLVMGetBitcodeModuleInContext(ContextRef: C, MemBuf: MB, OutM: &M, OutMessage: &msg);
47 else
48 Ret = LLVMParseBitcodeInContext(ContextRef: C, MemBuf: MB, OutModule: &M, OutMessage: &msg);
49 }
50
51 if (Ret) {
52 fprintf(stderr, format: "Error parsing bitcode: %s\n", msg);
53 LLVMDisposeMemoryBuffer(MemBuf: MB);
54 exit(status: 1);
55 }
56
57 if (!Lazy)
58 LLVMDisposeMemoryBuffer(MemBuf: MB);
59
60 return M;
61}
62
63int llvm_module_dump(bool Lazy, bool New) {
64 LLVMModuleRef M = llvm_load_module(C: LLVMGetGlobalContext(), Lazy, New);
65
66 char *irstr = LLVMPrintModuleToString(M);
67 puts(s: irstr);
68 LLVMDisposeMessage(Message: irstr);
69
70 LLVMDisposeModule(M);
71
72 return 0;
73}
74
75int llvm_module_list_functions(void) {
76 LLVMModuleRef M = llvm_load_module(C: LLVMGetGlobalContext(), false, false);
77 LLVMValueRef f;
78
79 f = LLVMGetFirstFunction(M);
80 while (f) {
81 if (LLVMIsDeclaration(Global: f)) {
82 printf(format: "FunctionDeclaration: %s\n", LLVMGetValueName(Val: f));
83 } else {
84 LLVMBasicBlockRef bb;
85 LLVMValueRef isn;
86 unsigned nisn = 0;
87 unsigned nbb = 0;
88
89 printf(format: "FunctionDefinition: %s [#bb=%u]\n", LLVMGetValueName(Val: f),
90 LLVMCountBasicBlocks(Fn: f));
91
92 for (bb = LLVMGetFirstBasicBlock(Fn: f); bb;
93 bb = LLVMGetNextBasicBlock(BB: bb)) {
94 nbb++;
95 for (isn = LLVMGetFirstInstruction(BB: bb); isn;
96 isn = LLVMGetNextInstruction(Inst: isn)) {
97 nisn++;
98 if (LLVMIsACallInst(Val: isn)) {
99 LLVMValueRef callee =
100 LLVMGetOperand(Val: isn, Index: LLVMGetNumOperands(Val: isn) - 1);
101 printf(format: " calls: %s\n", LLVMGetValueName(Val: callee));
102 }
103 }
104 }
105 printf(format: " #isn: %u\n", nisn);
106 printf(format: " #bb: %u\n\n", nbb);
107 }
108 f = LLVMGetNextFunction(Fn: f);
109 }
110
111 LLVMDisposeModule(M);
112
113 return 0;
114}
115
116int llvm_module_list_globals(void) {
117 LLVMModuleRef M = llvm_load_module(C: LLVMGetGlobalContext(), false, false);
118 LLVMValueRef g;
119
120 g = LLVMGetFirstGlobal(M);
121 while (g) {
122 LLVMTypeRef T = LLVMTypeOf(Val: g);
123 char *s = LLVMPrintTypeToString(Val: T);
124
125 printf(format: "Global%s: %s %s\n",
126 LLVMIsDeclaration(Global: g) ? "Declaration" : "Definition",
127 LLVMGetValueName(Val: g), s);
128
129 LLVMDisposeMessage(Message: s);
130
131 g = LLVMGetNextGlobal(GlobalVar: g);
132 }
133
134 LLVMDisposeModule(M);
135
136 return 0;
137}
138