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, "Error with new bitcode parser: %s\n", CErr);
23  LLVMDisposeMessage(CErr);
24  exit(1);
25}
26
27LLVMModuleRef llvm_load_module(bool Lazy, bool New) {
28  LLVMMemoryBufferRef MB;
29  LLVMModuleRef M;
30  char *msg = NULL;
31
32  if (LLVMCreateMemoryBufferWithSTDIN(&MB, &msg)) {
33    fprintf(stderr, "Error reading file: %s\n", msg);
34    exit(1);
35  }
36
37  LLVMBool Ret;
38  if (New) {
39    LLVMContextRef C = LLVMGetGlobalContext();
40    LLVMContextSetDiagnosticHandler(C, diagnosticHandler, NULL);
41    if (Lazy)
42      Ret = LLVMGetBitcodeModule2(MB, &M);
43    else
44      Ret = LLVMParseBitcode2(MB, &M);
45  } else {
46    if (Lazy)
47      Ret = LLVMGetBitcodeModule(MB, &M, &msg);
48    else
49      Ret = LLVMParseBitcode(MB, &M, &msg);
50  }
51
52  if (Ret) {
53    fprintf(stderr, "Error parsing bitcode: %s\n", msg);
54    LLVMDisposeMemoryBuffer(MB);
55    exit(1);
56  }
57
58  if (!Lazy)
59    LLVMDisposeMemoryBuffer(MB);
60
61  return M;
62}
63
64int llvm_module_dump(bool Lazy, bool New) {
65  LLVMModuleRef M = llvm_load_module(Lazy, New);
66
67  char *irstr = LLVMPrintModuleToString(M);
68  puts(irstr);
69  LLVMDisposeMessage(irstr);
70
71  LLVMDisposeModule(M);
72
73  return 0;
74}
75
76int llvm_module_list_functions(void) {
77  LLVMModuleRef M = llvm_load_module(false, false);
78  LLVMValueRef f;
79
80  f = LLVMGetFirstFunction(M);
81  while (f) {
82    if (LLVMIsDeclaration(f)) {
83      printf("FunctionDeclaration: %s\n", LLVMGetValueName(f));
84    } else {
85      LLVMBasicBlockRef bb;
86      LLVMValueRef isn;
87      unsigned nisn = 0;
88      unsigned nbb = 0;
89
90      printf("FunctionDefinition: %s [#bb=%u]\n", LLVMGetValueName(f),
91             LLVMCountBasicBlocks(f));
92
93      for (bb = LLVMGetFirstBasicBlock(f); bb;
94           bb = LLVMGetNextBasicBlock(bb)) {
95        nbb++;
96        for (isn = LLVMGetFirstInstruction(bb); isn;
97             isn = LLVMGetNextInstruction(isn)) {
98          nisn++;
99          if (LLVMIsACallInst(isn)) {
100            LLVMValueRef callee =
101                LLVMGetOperand(isn, LLVMGetNumOperands(isn) - 1);
102            printf(" calls: %s\n", LLVMGetValueName(callee));
103          }
104        }
105      }
106      printf(" #isn: %u\n", nisn);
107      printf(" #bb: %u\n\n", nbb);
108    }
109    f = LLVMGetNextFunction(f);
110  }
111
112  LLVMDisposeModule(M);
113
114  return 0;
115}
116
117int llvm_module_list_globals(void) {
118  LLVMModuleRef M = llvm_load_module(false, false);
119  LLVMValueRef g;
120
121  g = LLVMGetFirstGlobal(M);
122  while (g) {
123    LLVMTypeRef T = LLVMTypeOf(g);
124    char *s = LLVMPrintTypeToString(T);
125
126    printf("Global%s: %s %s\n",
127           LLVMIsDeclaration(g) ? "Declaration" : "Definition",
128           LLVMGetValueName(g), s);
129
130    LLVMDisposeMessage(s);
131
132    g = LLVMGetNextGlobal(g);
133  }
134
135  LLVMDisposeModule(M);
136
137  return 0;
138}
139