Add llvm-c-test tool for testing llvm-c
authorAnders Waldenborg <anders@0x63.nu>
Wed, 23 Oct 2013 08:10:20 +0000 (08:10 +0000)
committerAnders Waldenborg <anders@0x63.nu>
Wed, 23 Oct 2013 08:10:20 +0000 (08:10 +0000)
This provides rudimentary testing of the llvm-c api.

The following commands are implemented:

  * --module-dump
    Read bytecode from stdin - print ir

  * --module-list-functions
    Read bytecode from stdin - list summary of functions

  * --module-list-globals
    Read bytecode from stdin - list summary of globals

  * --targets-list
    List available targets

  * --object-list-sections
    Read object file from stdin - list sections

  * --object-list-symbols
    Read object file from stdin - list symbols (like nm)

  * --disassemble
    Read lines of triple, hex ascii machine code from stdin - print disassembly

  * --calc
    Read lines of name, rpn from stdin - print generated module ir

Differential-Revision: http://llvm-reviews.chandlerc.com/D1776
llvm-svn: 193233

19 files changed:
llvm/test/Bindings/llvm-c/calc.test [new file with mode: 0644]
llvm/test/Bindings/llvm-c/disassemble.test [new file with mode: 0644]
llvm/test/Bindings/llvm-c/functions.ll [new file with mode: 0644]
llvm/test/Bindings/llvm-c/globals.ll [new file with mode: 0644]
llvm/test/Bindings/llvm-c/lit.local.cfg [new file with mode: 0644]
llvm/test/lit.cfg
llvm/tools/CMakeLists.txt
llvm/tools/Makefile
llvm/tools/llvm-c-test/CMakeLists.txt [new file with mode: 0644]
llvm/tools/llvm-c-test/Makefile [new file with mode: 0644]
llvm/tools/llvm-c-test/calc.c [new file with mode: 0644]
llvm/tools/llvm-c-test/disassemble.c [new file with mode: 0644]
llvm/tools/llvm-c-test/helpers.c [new file with mode: 0644]
llvm/tools/llvm-c-test/include-all.c [new file with mode: 0644]
llvm/tools/llvm-c-test/llvm-c-test.h [new file with mode: 0644]
llvm/tools/llvm-c-test/main.c [new file with mode: 0644]
llvm/tools/llvm-c-test/module.c [new file with mode: 0644]
llvm/tools/llvm-c-test/object.c [new file with mode: 0644]
llvm/tools/llvm-c-test/targets.c [new file with mode: 0644]

diff --git a/llvm/test/Bindings/llvm-c/calc.test b/llvm/test/Bindings/llvm-c/calc.test
new file mode 100644 (file)
index 0000000..36a76e6
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: llvm-c-test --calc <%s | FileCheck %s
+
+; constant folding
+test 100 200 +
+;CHECK: ModuleID = 'test'
+;CHECK: define i64 @test
+;CHECK: {
+;CHECK: ret i64 300
+;CHECK: }
+
+arg1 0 @ 0 @ * 1 @ 1 @ * +
+;CHECK: ModuleID = 'arg1'
+;CHECK: getelementptr
+;CHECK: load
+;CHECK: ret
diff --git a/llvm/test/Bindings/llvm-c/disassemble.test b/llvm/test/Bindings/llvm-c/disassemble.test
new file mode 100644 (file)
index 0000000..201e914
--- /dev/null
@@ -0,0 +1,29 @@
+; RUN: llvm-c-test --disassemble < %s | FileCheck %s
+
+
+arm-linux-android    44 26 1f e5 0c 10 4b e2 02 20 81 e0
+;CHECK: triple: arm-linux-android
+;CHECK: ldr    r2, [pc, #-1604]
+;CHECK: sub    r1, r11, #12
+;CHECK: 02 20 81 e0
+;CHECK: add    r2, r1, r2
+
+x86_64-linux-unknown 48 83 c4 38 5b 5d 41 5c 41 5d 41 5e 41 5f c3
+;CHECK: triple: x86_64-linux-unknown
+;CHECK: addq   $56, %rsp
+;CHECK: popq   %rbx
+;CHECK: popq   %rbp
+;CHECK: popq   %r12
+;CHECK: popq   %r13
+;CHECK: popq   %r14
+;CHECK: popq   %r15
+;CHECK: ret
+
+i686-apple-darwin    0f b7 4c 24 0a e8 29 ce ff ff
+;CHECK: movzwl 10(%esp), %ecx
+;CHECK: calll  -12759
+
+i686-linux-unknown   dd 44 24 04 d9 e1 c3
+;CHECK: fldl   4(%esp)
+;CHECK: fabs
+;CHECK: ret
diff --git a/llvm/test/Bindings/llvm-c/functions.ll b/llvm/test/Bindings/llvm-c/functions.ll
new file mode 100644 (file)
index 0000000..4503fb1
--- /dev/null
@@ -0,0 +1,31 @@
+; RUN: llvm-as < %s | llvm-c-test --module-list-functions | FileCheck %s
+
+define i32 @X() {
+entry:
+  br label %l1
+
+l1:
+  br label %l2
+
+l2:
+  br label %l3
+
+l3:
+  ret i32 1234
+}
+;CHECK: FunctionDefinition: X [#bb=4]
+
+
+define i32 @Z(i32 %a) {
+entry:
+  %0 = tail call i32 @Y(i32 %a)
+  ret i32 %0
+}
+
+;CHECK: FunctionDefinition: Z [#bb=1]
+;CHECK:  calls: Y
+;CHECK:  #isn: 2
+
+declare i32 @Y(i32)
+;CHECK: FunctionDeclaration: Y
+
diff --git a/llvm/test/Bindings/llvm-c/globals.ll b/llvm/test/Bindings/llvm-c/globals.ll
new file mode 100644 (file)
index 0000000..a38f08b
--- /dev/null
@@ -0,0 +1,7 @@
+; RUN: llvm-as < %s | llvm-c-test --module-list-globals | FileCheck %s
+
+@foo = constant [7 x i8] c"foobar\00", align 1
+;CHECK: GlobalDefinition: foo [7 x i8]*
+
+@bar = common global i32 0, align 4
+;CHECK: GlobalDefinition: bar i32*
diff --git a/llvm/test/Bindings/llvm-c/lit.local.cfg b/llvm/test/Bindings/llvm-c/lit.local.cfg
new file mode 100644 (file)
index 0000000..270a7f2
--- /dev/null
@@ -0,0 +1,3 @@
+targets = set(config.root.targets_to_build.split())
+if not (targets & set(["X86", "ARM"])):
+    config.unsupported = True
index 9e590a8..1b6fa54 100644 (file)
@@ -232,6 +232,7 @@ for pattern in [r"\bbugpoint\b(?!-)",
                 r"\bllvm-shlib\b",
                 r"\bllvm-size\b",
                 r"\bllvm-tblgen\b",
+                r"\bllvm-c-test\b",
                 # Match llvmc but not -llvmc
                 NOHYPHEN + r"\bllvmc\b",
                 # Match lto but not -lto
index 69c4050..54f849c 100644 (file)
@@ -39,6 +39,12 @@ add_llvm_tool_subdirectory(llvm-mcmarkup)
 
 add_llvm_tool_subdirectory(llvm-symbolizer)
 
+if( NOT MSVC )
+  add_llvm_tool_subdirectory(llvm-c-test)
+else()
+  ignore_llvm_tool_subdirectory(llvm-c-test)
+endif( NOT MSVC )
+
 add_llvm_tool_subdirectory(obj2yaml)
 add_llvm_tool_subdirectory(yaml2obj)
 
index 5fa5bf2..be87254 100644 (file)
@@ -31,7 +31,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis llc llvm-ar llvm-nm llvm-link \
                  lli llvm-extract llvm-mc bugpoint llvm-bcanalyzer llvm-diff \
                  macho-dump llvm-objdump llvm-readobj llvm-rtdyld \
                  llvm-dwarfdump llvm-cov llvm-size llvm-stress llvm-mcmarkup \
-                 llvm-symbolizer obj2yaml yaml2obj
+                 llvm-symbolizer obj2yaml yaml2obj llvm-c-test
 
 # If Intel JIT Events support is configured, build an extra tool to test it.
 ifeq ($(USE_INTEL_JITEVENTS), 1)
diff --git a/llvm/tools/llvm-c-test/CMakeLists.txt b/llvm/tools/llvm-c-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2926d9d
--- /dev/null
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS all)
+
+if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wstrict-prototypes")
+endif ()
+
+add_llvm_tool(llvm-c-test
+  calc.c
+  disassemble.c
+  helpers.c
+  include-all.c
+  main.c
+  module.c
+  object.c
+  targets.c
+  )
diff --git a/llvm/tools/llvm-c-test/Makefile b/llvm/tools/llvm-c-test/Makefile
new file mode 100644 (file)
index 0000000..08be7c3
--- /dev/null
@@ -0,0 +1,29 @@
+##===- tools/llvm-c-test -----------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TOOLNAME = llvm-c-test
+
+TOOL_NO_EXPORTS = 1
+NO_INSTALL = 1
+
+
+# If there is no shared lib, link all components...
+ifneq ($(ENABLE_SHARED),1)
+LINK_COMPONENTS = all
+endif
+
+include $(LEVEL)/Makefile.common
+
+CFLAGS += -std=c99 -Wall -Wstrict-prototypes
+
+# ...but if it is built - use it
+ifeq ($(ENABLE_SHARED),1)
+LIBS = -lLLVM-$(LLVMVersion)
+endif
diff --git a/llvm/tools/llvm-c-test/calc.c b/llvm/tools/llvm-c-test/calc.c
new file mode 100644 (file)
index 0000000..c34ff7b
--- /dev/null
@@ -0,0 +1,143 @@
+/*===-- calc.c - tool for testing libLLVM and llvm-c API ------------------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file implements the --calc command in llvm-c-test. --calc reads lines *|
+|* from stdin, parses them as a name and an expression in reverse polish      *|
+|* notation and prints a module with a function with the expression.          *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c-test.h"
+#include "llvm-c/Core.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+typedef LLVMValueRef (*binop_func_t)(LLVMBuilderRef, LLVMValueRef LHS,
+                                     LLVMValueRef RHS, const char *Name);
+
+static LLVMOpcode op_to_opcode(char op) {
+  switch (op) {
+  case '+': return LLVMAdd;
+  case '-': return LLVMSub;
+  case '*': return LLVMMul;
+  case '/': return LLVMSDiv;
+  case '&': return LLVMAnd;
+  case '|': return LLVMOr;
+  case '^': return LLVMXor;
+  }
+  assert(0 && "unknown operation");
+  return 0;
+}
+
+#define MAX_DEPTH 32
+
+static LLVMValueRef build_from_tokens(char **tokens, int ntokens,
+                                      LLVMBuilderRef builder,
+                                      LLVMValueRef param) {
+  LLVMValueRef stack[MAX_DEPTH];
+  int depth = 0;
+
+  for (int i = 0; i < ntokens; i++) {
+    char tok = tokens[i][0];
+    switch (tok) {
+    case '+':
+    case '-':
+    case '*':
+    case '/':
+    case '&':
+    case '|':
+    case '^':
+      if (depth < 2) {
+        printf("stack underflow\n");
+        return NULL;
+      }
+
+      stack[depth - 2] = LLVMBuildBinOp(builder, op_to_opcode(tok),
+                                        stack[depth - 1], stack[depth - 2], "");
+      depth--;
+
+      break;
+
+    case '@':
+      if (depth < 1) {
+        printf("stack underflow\n");
+        return NULL;
+      }
+
+      LLVMValueRef off = LLVMBuildGEP(builder, param, &stack[depth - 1], 1, "");
+      stack[depth - 1] = LLVMBuildLoad(builder, off, "");
+
+      break;
+
+    default: {
+      char *end;
+      long val = strtol(tokens[i], &end, 0);
+      if (end[0] != '\0') {
+        printf("error parsing number\n");
+        return NULL;
+      }
+
+      if (depth >= MAX_DEPTH) {
+        printf("stack overflow\n");
+        return NULL;
+      }
+
+      stack[depth++] = LLVMConstInt(LLVMInt64Type(), val, 1);
+      break;
+    }
+    }
+  }
+
+  if (depth < 1) {
+    printf("stack underflow at return\n");
+    return NULL;
+  }
+
+  LLVMBuildRet(builder, stack[depth - 1]);
+
+  return stack[depth - 1];
+}
+
+static void handle_line(char **tokens, int ntokens) {
+  char *name = tokens[0];
+
+  LLVMModuleRef M = LLVMModuleCreateWithName(name);
+
+  LLVMTypeRef I64ty = LLVMInt64Type();
+  LLVMTypeRef I64Ptrty = LLVMPointerType(I64ty, 0);
+  LLVMTypeRef Fty = LLVMFunctionType(I64ty, &I64Ptrty, 1, 0);
+
+  LLVMValueRef F = LLVMAddFunction(M, name, Fty);
+  LLVMBuilderRef builder = LLVMCreateBuilder();
+  LLVMPositionBuilderAtEnd(builder, LLVMAppendBasicBlock(F, "entry"));
+
+  LLVMValueRef param;
+  LLVMGetParams(F, &param);
+  LLVMSetValueName(param, "in");
+
+  LLVMValueRef res = build_from_tokens(tokens + 1, ntokens - 1, builder, param);
+  if (res) {
+    char *irstr = LLVMPrintModuleToString(M);
+    puts(irstr);
+    LLVMDisposeMessage(irstr);
+  }
+
+  LLVMDisposeBuilder(builder);
+
+  LLVMDisposeModule(M);
+}
+
+int calc(void) {
+
+  tokenize_stdin(handle_line);
+
+  return 0;
+}
diff --git a/llvm/tools/llvm-c-test/disassemble.c b/llvm/tools/llvm-c-test/disassemble.c
new file mode 100644 (file)
index 0000000..4b3d37b
--- /dev/null
@@ -0,0 +1,85 @@
+/*===-- disassemble.c - tool for testing libLLVM and llvm-c API -----------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file implements the --disassemble command in llvm-c-test.             *|
+|* --disassemble reads lines from stdin, parses them as a triple and hex      *|
+|*  machine code, and prints disassembly of the machine code.                 *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c-test.h"
+#include "llvm-c/Disassembler.h"
+#include "llvm-c/Target.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static void pprint(int pos, unsigned char *buf, int len, const char *disasm) {
+  printf("%04x:  ", pos);
+  for (int i = 0; i < 8; i++) {
+    if (i < len) {
+      printf("%02x ", buf[i]);
+    } else {
+      printf("   ");
+    }
+  }
+
+  printf("   %s\n", disasm);
+}
+
+static void do_disassemble(const char *triple, unsigned char *buf, int siz) {
+  LLVMDisasmContextRef D = LLVMCreateDisasm(triple, NULL, 0, NULL, NULL);
+
+  if (!D) {
+    printf("ERROR: Couldn't create disassebler for triple %s\n", triple);
+    return;
+  }
+
+  char outline[1024];
+  int pos = 0;
+  while (pos < siz) {
+    size_t l = LLVMDisasmInstruction(D, buf + pos, siz - pos, 0, outline,
+                                     sizeof(outline));
+    if (!l) {
+      pprint(pos, buf + pos, 1, "\t???");
+      pos++;
+    } else {
+      pprint(pos, buf + pos, l, outline);
+      pos += l;
+    }
+  }
+
+  LLVMDisasmDispose(D);
+}
+
+static void handle_line(char **tokens, int ntokens) {
+  unsigned char disbuf[128];
+  size_t disbuflen = 0;
+  char *triple = tokens[0];
+
+  printf("triple: %s\n", triple);
+
+  for (int i = 1; i < ntokens; i++) {
+    disbuf[disbuflen++] = strtol(tokens[i], NULL, 16);
+    if (disbuflen >= sizeof(disbuf)) {
+      fprintf(stderr, "Warning: Too long line, truncating\n");
+      break;
+    }
+  }
+  do_disassemble(triple, disbuf, disbuflen);
+}
+
+int disassemble(void) {
+  LLVMInitializeAllTargetInfos();
+  LLVMInitializeAllTargetMCs();
+  LLVMInitializeAllDisassemblers();
+
+  tokenize_stdin(handle_line);
+
+  return 0;
+}
diff --git a/llvm/tools/llvm-c-test/helpers.c b/llvm/tools/llvm-c-test/helpers.c
new file mode 100644 (file)
index 0000000..1ea8a4f
--- /dev/null
@@ -0,0 +1,40 @@
+/*===-- helpers.c - tool for testing libLLVM and llvm-c API ---------------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* Helper functions                                                           *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c-test.h"
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_TOKENS 512
+#define MAX_LINE_LEN 1024
+
+void tokenize_stdin(void (*cb)(char **tokens, int ntokens)) {
+  char line[MAX_LINE_LEN];
+  char *tokbuf[MAX_TOKENS];
+
+  while (fgets(line, sizeof(line), stdin)) {
+    int c = 0;
+
+    if (line[0] == ';' || line[0] == '\n')
+      continue;
+
+    while (c < MAX_TOKENS) {
+      tokbuf[c] = strtok(c ? NULL : line, " \n");
+      if (!tokbuf[c])
+        break;
+      c++;
+    }
+    if (c)
+      cb(tokbuf, c);
+  }
+}
diff --git a/llvm/tools/llvm-c-test/include-all.c b/llvm/tools/llvm-c-test/include-all.c
new file mode 100644 (file)
index 0000000..17b9917
--- /dev/null
@@ -0,0 +1,33 @@
+/*===-- include-all.c - tool for testing libLLVM and llvm-c API -----------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file doesn't have any actual code. It just make sure that all         *|
+|* the llvm-c include files are good and doesn't generate any warnings        *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+// FIXME: Autogenerate this list
+
+#include "llvm-c/Analysis.h"
+#include "llvm-c/BitReader.h"
+#include "llvm-c/BitWriter.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/Disassembler.h"
+#include "llvm-c/ExecutionEngine.h"
+#include "llvm-c/Initialization.h"
+#include "llvm-c/LinkTimeOptimizer.h"
+#include "llvm-c/Linker.h"
+#include "llvm-c/Object.h"
+#include "llvm-c/Target.h"
+#include "llvm-c/TargetMachine.h"
+#include "llvm-c/Transforms/IPO.h"
+#include "llvm-c/Transforms/PassManagerBuilder.h"
+#include "llvm-c/Transforms/Scalar.h"
+#include "llvm-c/Transforms/Vectorize.h"
+#include "llvm-c/lto.h"
diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h
new file mode 100644 (file)
index 0000000..0a25aa6
--- /dev/null
@@ -0,0 +1,37 @@
+/*===-- llvm-c-test.h - tool for testing libLLVM and llvm-c API -----------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* Header file for llvm-c-test                                                *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+#ifndef LLVM_C_TEST_H
+#define LLVM_C_TEST_H
+
+// helpers.c
+void tokenize_stdin(void (*cb)(char **tokens, int ntokens));
+
+// module.c
+int module_dump(void);
+int module_list_functions(void);
+int module_list_globals(void);
+
+// calc.c
+int calc(void);
+
+// disassemble.c
+int disassemble(void);
+
+// object.c
+int object_list_sections(void);
+int object_list_symbols(void);
+
+// targets.c
+int targets_list(void);
+
+#endif
diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c
new file mode 100644 (file)
index 0000000..72f8b04
--- /dev/null
@@ -0,0 +1,73 @@
+/*===-- main.c - tool for testing libLLVM and llvm-c API ------------------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* Main file for llvm-c-tests. "Parses" arguments and dispatches.             *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c-test.h"
+#include "llvm-c/BitReader.h"
+#include "llvm-c/Core.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void print_usage(void) {
+  fprintf(stderr, "llvm-c-test command\n\n");
+  fprintf(stderr, " Commands:\n");
+  fprintf(stderr, "  * --module-dump\n");
+  fprintf(stderr, "    Read bytecode from stdin - print disassembly\n\n");
+  fprintf(stderr, "  * --module-list-functions\n");
+  fprintf(stderr,
+          "    Read bytecode from stdin - list summary of functions\n\n");
+  fprintf(stderr, "  * --module-list-globals\n");
+  fprintf(stderr, "    Read bytecode from stdin - list summary of globals\n\n");
+  fprintf(stderr, "  * --targets-list\n");
+  fprintf(stderr, "    List available targets\n\n");
+  fprintf(stderr, "  * --object-list-sections\n");
+  fprintf(stderr, "    Read object file form stdin - list sections\n\n");
+  fprintf(stderr, "  * --object-list-symbols\n");
+  fprintf(stderr,
+          "    Read object file form stdin - list symbols (like nm)\n\n");
+  fprintf(stderr, "  * --disassemble\n");
+  fprintf(stderr, "    Read lines of triple, hex ascii machine code from stdin "
+                  "- print disassembly\n\n");
+  fprintf(stderr, "  * --calc\n");
+  fprintf(
+      stderr,
+      "    Read lines of name, rpn from stdin - print generated module\n\n");
+}
+
+int main(int argc, char **argv) {
+  LLVMPassRegistryRef pr = LLVMGetGlobalPassRegistry();
+
+  LLVMInitializeCore(pr);
+
+  if (argc == 2 && !strcmp(argv[1], "--module-dump")) {
+    return module_dump();
+  } else if (argc == 2 && !strcmp(argv[1], "--module-list-functions")) {
+    return module_list_functions();
+  } else if (argc == 2 && !strcmp(argv[1], "--module-list-globals")) {
+    return module_list_globals();
+  } else if (argc == 2 && !strcmp(argv[1], "--targets-list")) {
+    return targets_list();
+  } else if (argc == 2 && !strcmp(argv[1], "--object-list-sections")) {
+    return object_list_sections();
+  } else if (argc == 2 && !strcmp(argv[1], "--object-list-symbols")) {
+    return object_list_symbols();
+  } else if (argc == 2 && !strcmp(argv[1], "--disassemble")) {
+    return disassemble();
+  } else if (argc == 2 && !strcmp(argv[1], "--calc")) {
+    return calc();
+  } else {
+    print_usage();
+  }
+
+  return 1;
+}
diff --git a/llvm/tools/llvm-c-test/module.c b/llvm/tools/llvm-c-test/module.c
new file mode 100644 (file)
index 0000000..50e6e9c
--- /dev/null
@@ -0,0 +1,112 @@
+/*===-- module.c - tool for testing libLLVM and llvm-c API ----------------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file implements the --module-dump, --module-list-functions and        *|
+|* --module-list-globals commands in llvm-c-test.                             *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c-test.h"
+#include "llvm-c/BitReader.h"
+#include "llvm-c/Core.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static LLVMModuleRef load_module(void) {
+  LLVMMemoryBufferRef MB;
+  LLVMModuleRef M;
+  char *msg = NULL;
+
+  if (LLVMCreateMemoryBufferWithSTDIN(&MB, &msg)) {
+    fprintf(stderr, "Error reading file: %s\n", msg);
+    exit(1);
+  }
+
+  if (LLVMParseBitcode(MB, &M, &msg)) {
+    fprintf(stderr, "Error parsing bitcode: %s\n", msg);
+    exit(1);
+  }
+
+  return M;
+}
+
+int module_dump(void) {
+  LLVMModuleRef M = load_module();
+
+  char *irstr = LLVMPrintModuleToString(M);
+  puts(irstr);
+  LLVMDisposeMessage(irstr);
+
+  LLVMDisposeModule(M);
+
+  return 0;
+}
+
+int module_list_functions(void) {
+  LLVMModuleRef M = load_module();
+  LLVMValueRef f;
+
+  f = LLVMGetFirstFunction(M);
+  while (f) {
+    if (LLVMIsDeclaration(f)) {
+      printf("FunctionDeclaration: %s\n", LLVMGetValueName(f));
+    } else {
+      unsigned nisn = 0;
+      unsigned nbb = 0;
+
+      printf("FunctionDefinition: %s [#bb=%u]\n", LLVMGetValueName(f),
+             LLVMCountBasicBlocks(f));
+
+      for (LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(f); bb;
+           bb = LLVMGetNextBasicBlock(bb)) {
+        nbb++;
+        for (LLVMValueRef isn = LLVMGetFirstInstruction(bb); isn;
+             isn = LLVMGetNextInstruction(isn)) {
+          nisn++;
+          if (LLVMIsACallInst(isn)) {
+            LLVMValueRef callee =
+                LLVMGetOperand(isn, LLVMGetNumOperands(isn) - 1);
+            printf(" calls: %s\n", LLVMGetValueName(callee));
+          }
+        }
+      }
+      printf(" #isn: %u\n", nisn);
+      printf(" #bb: %u\n\n", nbb);
+    }
+    f = LLVMGetNextFunction(f);
+  }
+
+  LLVMDisposeModule(M);
+
+  return 0;
+}
+
+int module_list_globals(void) {
+  LLVMModuleRef M = load_module();
+  LLVMValueRef g;
+
+  g = LLVMGetFirstGlobal(M);
+  while (g) {
+    LLVMTypeRef T = LLVMTypeOf(g);
+    char *s = LLVMPrintTypeToString(T);
+
+    printf("Global%s: %s %s\n",
+           LLVMIsDeclaration(g) ? "Declaration" : "Definition",
+           LLVMGetValueName(g), s);
+
+    LLVMDisposeMessage(s);
+
+    g = LLVMGetNextGlobal(g);
+  }
+
+  LLVMDisposeModule(M);
+
+  return 0;
+}
diff --git a/llvm/tools/llvm-c-test/object.c b/llvm/tools/llvm-c-test/object.c
new file mode 100644 (file)
index 0000000..c94e3af
--- /dev/null
@@ -0,0 +1,85 @@
+/*===-- object.c - tool for testing libLLVM and llvm-c API ----------------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file implements the --object-list-sections and --object-list-symbols  *|
+|* commands in llvm-c-test.                                                   *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c-test.h"
+#include "llvm-c/Object.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int object_list_sections(void) {
+  LLVMMemoryBufferRef MB;
+  LLVMObjectFileRef O;
+  char *msg = NULL;
+
+  if (LLVMCreateMemoryBufferWithSTDIN(&MB, &msg)) {
+    fprintf(stderr, "Error reading file: %s\n", msg);
+    exit(1);
+  }
+
+  O = LLVMCreateObjectFile(MB);
+  if (!O) {
+    fprintf(stderr, "Error reading object\n");
+    exit(1);
+  }
+
+  LLVMSectionIteratorRef sect = LLVMGetSections(O);
+  while (!LLVMIsSectionIteratorAtEnd(O, sect)) {
+    printf("'%s': @0x%08" PRIx64 " +%" PRIu64 "\n", LLVMGetSectionName(sect),
+           LLVMGetSectionAddress(sect), LLVMGetSectionSize(sect));
+
+    LLVMMoveToNextSection(sect);
+  }
+
+  LLVMDisposeSectionIterator(sect);
+
+  LLVMDisposeObjectFile(O);
+
+  return 0;
+}
+
+int object_list_symbols(void) {
+  LLVMMemoryBufferRef MB;
+  LLVMObjectFileRef O;
+  char *msg = NULL;
+
+  if (LLVMCreateMemoryBufferWithSTDIN(&MB, &msg)) {
+    fprintf(stderr, "Error reading file: %s\n", msg);
+    exit(1);
+  }
+
+  O = LLVMCreateObjectFile(MB);
+  if (!O) {
+    fprintf(stderr, "Error reading object\n");
+    exit(1);
+  }
+
+  LLVMSectionIteratorRef sect = LLVMGetSections(O);
+  LLVMSymbolIteratorRef sym = LLVMGetSymbols(O);
+  while (!LLVMIsSymbolIteratorAtEnd(O, sym)) {
+
+    LLVMMoveToContainingSection(sect, sym);
+    printf("%s @0x%08" PRIx64 "/0x%08" PRIx64 " +%" PRIu64 " (%s)\n",
+           LLVMGetSymbolName(sym), LLVMGetSymbolAddress(sym),
+           LLVMGetSymbolFileOffset(sym), LLVMGetSymbolSize(sym),
+           LLVMGetSectionName(sect));
+
+    LLVMMoveToNextSymbol(sym);
+  }
+
+  LLVMDisposeSymbolIterator(sym);
+
+  LLVMDisposeObjectFile(O);
+
+  return 0;
+}
diff --git a/llvm/tools/llvm-c-test/targets.c b/llvm/tools/llvm-c-test/targets.c
new file mode 100644 (file)
index 0000000..fccea09
--- /dev/null
@@ -0,0 +1,29 @@
+/*===-- targets.c - tool for testing libLLVM and llvm-c API ---------------===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This file implements the --targets command in llvm-c-test.                 *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm-c/TargetMachine.h"
+#include <stdio.h>
+
+int targets_list(void) {
+  LLVMInitializeAllTargetInfos();
+  LLVMInitializeAllTargets();
+
+  for (LLVMTargetRef t = LLVMGetFirstTarget(); t; t = LLVMGetNextTarget(t)) {
+    printf("%s", LLVMGetTargetName(t));
+    if (LLVMTargetHasJIT(t))
+      printf(" (+jit)");
+    printf("\n - %s\n", LLVMGetTargetDescription(t));
+  }
+
+  return 0;
+}