├── TODO ├── .clang-format ├── .gitignore ├── stop.jpg ├── inputs ├── with-headers1 │ ├── header_nested.h │ ├── header.h │ └── source.cpp ├── fptr.c ├── pass-nullptr.c ├── ptrtoptrparam.c ├── globals.c ├── iflhsptr.c ├── nullptr.cpp ├── funcwithattr.c ├── cfunc_with_if.c ├── basic-kernel-call.cu ├── xcudacxx11-repro.cpp ├── cstr-for-replacement.cpp ├── div0.c ├── funcallsample.cpp ├── nestedloops.c ├── threadidx.c ├── c_if_and_for.c ├── structinit.c ├── twodoublefoo.c ├── union.c ├── fact.c ├── README.rst ├── template-insts.cpp ├── vectortype.ll ├── simpleswitch.c ├── diamond-cfg.ll ├── namesp.cpp ├── types.c ├── assert.cc ├── using_builtins.c ├── loopy-cfg.ll ├── cuda_support_header.h ├── kernel-signatures.c ├── threadidx.ll ├── ctor-initializer-list.cpp ├── globals.ll ├── twodoublefoo.ll ├── typeuse.cpp ├── fact.ll ├── simpleswitch.ll ├── bigfunc.c └── types.ll ├── reformat.sh ├── using_clang_toolchain ├── README.rst ├── simple.cpp ├── warn_in_macro.cpp ├── cxx11-range-sample.cpp ├── exceptions1.cpp ├── memmain.c ├── memcaller.c └── Makefile ├── .vimrc ├── test ├── test_hello_pass_plugin.py ├── all_tests.py ├── test_clang_check.py ├── test_simple_module_pass.py ├── test_rewriter_sample.py ├── test_tooling_sample.py ├── test_simple_bb_pass.py ├── test_bb_toposort_sccs.py └── tools.py ├── src_clang ├── experimental │ ├── showattrs.py │ ├── callexpr.py │ ├── show-mangle.py │ ├── kernel-sigs.py │ ├── toplevel_decls.cpp │ ├── apply_replacements_with_rewriter.cpp │ ├── RemoveCStrCalls.cpp │ └── try_matcher.cpp ├── plugin_print_funcnames.cpp ├── matchers_rewriter.cpp ├── tooling_sample.cpp ├── rewritersample.cpp └── ClangCheck.cpp ├── tools ├── sample-js.js ├── template.html ├── show-cfg.py ├── gen_c_straightline.py └── htmlize-ast-dump.py ├── LICENSE ├── src_llvm ├── access_debug_metadata.cpp ├── hello_pass.cpp ├── experimental │ ├── loop_info.cpp │ └── build_llvm_ir.cpp ├── simple_module_pass.cpp ├── simple_bb_pass.cpp ├── analyze_geps.cpp ├── replace_threadidx_with_call.cpp └── bb_toposort_sccs.cpp ├── README.rst └── Makefile /TODO: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.pyc 3 | *.dot 4 | 5 | -------------------------------------------------------------------------------- /stop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eliben/llvm-clang-samples/HEAD/stop.jpg -------------------------------------------------------------------------------- /inputs/with-headers1/header_nested.h: -------------------------------------------------------------------------------- 1 | int int_from_nested; 2 | float float_from_nested; 3 | -------------------------------------------------------------------------------- /reformat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | pss --cpp -f src_llvm src_clang | xargs clang-format -style=LLVM -i 5 | -------------------------------------------------------------------------------- /inputs/fptr.c: -------------------------------------------------------------------------------- 1 | extern void (*v)(void*); 2 | 3 | void foo(int* x, int *y, void (*f)(int*)) { 4 | v = f; 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /inputs/with-headers1/header.h: -------------------------------------------------------------------------------- 1 | int int_from_header; 2 | 3 | #include "header_nested.h" 4 | 5 | double double_from_header; 6 | -------------------------------------------------------------------------------- /inputs/with-headers1/source.cpp: -------------------------------------------------------------------------------- 1 | #include "header.h" 2 | 3 | struct { 4 | int a; 5 | int b; 6 | } struct_from_source; 7 | -------------------------------------------------------------------------------- /using_clang_toolchain/README.rst: -------------------------------------------------------------------------------- 1 | These are samples of using the Clang+LLVM toolchain for building actual 2 | executables. 3 | -------------------------------------------------------------------------------- /inputs/pass-nullptr.c: -------------------------------------------------------------------------------- 1 | int foo(char* a, char* b); 2 | 3 | 4 | int bar() { 5 | char c; 6 | foo(&c, 0); 7 | return c; 8 | } 9 | -------------------------------------------------------------------------------- /inputs/ptrtoptrparam.c: -------------------------------------------------------------------------------- 1 | char foo(char** ppc, char a, char b) { 2 | char* pc = *ppc; 3 | char c = pc[1]; 4 | return c; 5 | } 6 | -------------------------------------------------------------------------------- /inputs/globals.c: -------------------------------------------------------------------------------- 1 | int gint; 2 | float gfloat; 3 | 4 | float** gppfloat; 5 | 6 | float foo() { 7 | return gfloat + **gppfloat; 8 | } 9 | -------------------------------------------------------------------------------- /inputs/iflhsptr.c: -------------------------------------------------------------------------------- 1 | int foo(int* p, int v) { 2 | if (p == 0) { 3 | return v + 1; 4 | } else { 5 | return v - 1; 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /inputs/nullptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int *foo() { 4 | #ifdef FOO 5 | return 0; 6 | #else 7 | return NULL; 8 | #endif 9 | } 10 | -------------------------------------------------------------------------------- /using_clang_toolchain/simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) { 4 | std::cout << "Hello world\n"; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /inputs/funcwithattr.c: -------------------------------------------------------------------------------- 1 | __attribute__((device)) void foodev() { 2 | } 3 | 4 | __attribute__((global)) void barglob() { 5 | } 6 | 7 | void baznone() { 8 | } 9 | -------------------------------------------------------------------------------- /inputs/cfunc_with_if.c: -------------------------------------------------------------------------------- 1 | void foo(int* a, int *b) { 2 | if (a[0] > 1) { 3 | b[0] = 2; 4 | } 5 | } 6 | 7 | void bar(float x, float y); // just a declaration 8 | -------------------------------------------------------------------------------- /inputs/basic-kernel-call.cu: -------------------------------------------------------------------------------- 1 | __attribute__((global)) void kernel(int* in, int* out) {} 2 | 3 | 4 | void host_func_foobar(int* inbuf, int* outbuf) { 5 | kernel<<<1, 32>>>(inbuf, outbuf); 6 | } 7 | -------------------------------------------------------------------------------- /inputs/xcudacxx11-repro.cpp: -------------------------------------------------------------------------------- 1 | template struct K1 { T member; }; 2 | 3 | template struct K2 { T member; }; 4 | 5 | template struct K3 { T member; }; 6 | 7 | K3>> var; 8 | -------------------------------------------------------------------------------- /inputs/cstr-for-replacement.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int foo(std::string s); 4 | 5 | int bar(std::string joe) { 6 | // This c_str() call should be replaced by remov-cstr-calls 7 | return foo(joe.c_str()); 8 | } 9 | -------------------------------------------------------------------------------- /inputs/div0.c: -------------------------------------------------------------------------------- 1 | #define DODIV(a, b) ((a) / (b)) 2 | 3 | int test(int z) { 4 | if (z == 0) { 5 | #ifdef FOO 6 | return DODIV(1, z); 7 | #else 8 | return 1 - z; 9 | #endif 10 | } 11 | return 1 + z; 12 | } 13 | -------------------------------------------------------------------------------- /inputs/funcallsample.cpp: -------------------------------------------------------------------------------- 1 | bool foo() { return true; } 2 | 3 | void bar() { 4 | foo(); 5 | for (int i = 0; i < 10; ++i) 6 | foo(); 7 | } 8 | 9 | int main() { 10 | bar(); 11 | if (foo()) 12 | bar(); 13 | } 14 | -------------------------------------------------------------------------------- /inputs/nestedloops.c: -------------------------------------------------------------------------------- 1 | extern int bar(int); 2 | 3 | void foobar(int* x, int* y) { 4 | for (int i = x[0]; i < x[1]; ++i) { 5 | for (int j = x[2]; j < x[3]; ++j) { 6 | y[i - j] = x[i + j] - bar(x[j]); 7 | } 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /inputs/threadidx.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | unsigned x, y, z; 3 | } uint3; 4 | 5 | const extern uint3 threadIdx; 6 | 7 | 8 | int foo(int a, int b) { 9 | if (threadIdx.y > 5) { 10 | return a; 11 | } else { 12 | return b; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /inputs/c_if_and_for.c: -------------------------------------------------------------------------------- 1 | void foo(int* a, int *b) { 2 | if (a[0] > 1) { 3 | b[0] = 2; 4 | } 5 | } 6 | 7 | void bar(float x, float y); // just a declaration 8 | 9 | void bang(int* a, int v) { 10 | for (int i = 0; i < v; ++i) { 11 | a[i] -= i; 12 | } 13 | } -------------------------------------------------------------------------------- /inputs/structinit.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | unsigned x, y, z; 3 | } uint3; 4 | 5 | volatile extern uint3 vglob; 6 | 7 | unsigned foo(unsigned a, unsigned b, unsigned c) { 8 | uint3 temp = {a, b, c}; 9 | vglob = temp; 10 | return temp.x + temp.y + temp.z; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /inputs/twodoublefoo.c: -------------------------------------------------------------------------------- 1 | double foo(double a, double b) { 2 | return 2 * a + b; 3 | } 4 | 5 | __attribute__((noinline)) static double internal(double a, double b) { 6 | return a * b; 7 | } 8 | 9 | double bar(double a, double b) { 10 | return internal(a, b) * 10; 11 | } 12 | -------------------------------------------------------------------------------- /inputs/union.c: -------------------------------------------------------------------------------- 1 | typedef union { 2 | double dnum; 3 | int inum; 4 | float* fptr; 5 | } my_union; 6 | 7 | 8 | /*int foo(void* p) {*/ 9 | /*my_union mp = *((my_union*)p);*/ 10 | /*return mp.inum;*/ 11 | /*}*/ 12 | 13 | int bar(my_union* mu) { 14 | return mu[4].inum; 15 | } 16 | -------------------------------------------------------------------------------- /.vimrc: -------------------------------------------------------------------------------- 1 | " Force indentation styles for this directory 2 | autocmd FileType python set shiftwidth=4 3 | autocmd FileType python set tabstop=4 4 | autocmd FileType python set softtabstop=4 5 | 6 | autocmd FileType c set shiftwidth=2 7 | autocmd FileType c set tabstop=2 8 | autocmd FileType c set softtabstop=2 9 | -------------------------------------------------------------------------------- /inputs/fact.c: -------------------------------------------------------------------------------- 1 | unsigned mult(unsigned a, unsigned b) { 2 | unsigned s = 0; 3 | for (int i = 0; i < a; ++i) { 4 | s += b; 5 | } 6 | return s; 7 | } 8 | 9 | unsigned fact(unsigned a) { 10 | if (a <= 1) { 11 | return 1; 12 | } else { 13 | return a * fact(a - 1); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /using_clang_toolchain/warn_in_macro.cpp: -------------------------------------------------------------------------------- 1 | #define MYCHECK(a) (0 && 4) 2 | 3 | int main(int argc, char **argv) { 4 | 5 | // Warning here 6 | while (0 && 4) { 7 | } 8 | 9 | // But no warning here, since 4 comes from a macro 10 | while (MYCHECK(argc)) { 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /inputs/README.rst: -------------------------------------------------------------------------------- 1 | LLVM IR is in .ll files; if an .ll file has a corresponding .c file, then the 2 | .ll file can be generated by calling clang:: 3 | 4 | clang -cc1 -emit-llvm 5 | 6 | For an optimized version, the following can be used:: 7 | 8 | clang -O3 -c -emit-llvm z.c -S -o - 9 | 10 | -------------------------------------------------------------------------------- /inputs/template-insts.cpp: -------------------------------------------------------------------------------- 1 | template T foo(T a, T b) { 2 | T k = a; 3 | for (int i = 0; i < N; ++i) { 4 | k = k * a + b; 5 | } 6 | return k; 7 | } 8 | 9 | int intyfoo(int x, int y) { return foo(x, y); } 10 | 11 | float floatyfoo(float x, float y) { return foo(x, y); } 12 | -------------------------------------------------------------------------------- /inputs/vectortype.ll: -------------------------------------------------------------------------------- 1 | ; Example of using long vector types with arithmetic. 2 | ; 3 | ; llc -O3 inputs/vectortype.ll -o - 4 | ; 5 | ; also try with -mattr=avx2 for leveraging AVX2 instructions. 6 | 7 | define <512 x i32> @add_vecs(<512 x i32> %a, <512 x i32> %b) { 8 | %1 = add <512 x i32> %a, %b 9 | ret <512 x i32> %1 10 | } 11 | -------------------------------------------------------------------------------- /inputs/simpleswitch.c: -------------------------------------------------------------------------------- 1 | unsigned decide(unsigned char pred, unsigned a[10]) { 2 | if (pred > a[2]) { 3 | return a[3]; 4 | } 5 | switch (pred) { 6 | case 1: 7 | return a[0] + a[2]; 8 | case 2: 9 | return a[3] - a[4]; 10 | case 200: 11 | return a[5] * a[6]; 12 | default: 13 | break; 14 | } 15 | 16 | return a[9] * a[4]; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /using_clang_toolchain/cxx11-range-sample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | // Container initialization - shiny! 6 | std::vector nums = {1, 2, 3, 4, 5}; 7 | 8 | // auto + for-range loop - shiny^2! 9 | for (auto &n : nums) { 10 | std::cout << n << " "; 11 | } 12 | 13 | std::cout << std::endl; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /inputs/diamond-cfg.ll: -------------------------------------------------------------------------------- 1 | ; Crafted to have a diamond-like CFG for testing the CFG analysis 2 | ; samples. 3 | 4 | define i32 @func(i32 %a, i32 %b) #0 { 5 | AA: 6 | %cmp1 = icmp eq i32 %a, %b 7 | br i1 %cmp1, label %BB, label %CC 8 | 9 | BB: 10 | %cmp2 = icmp ult i32 %a, %b 11 | br i1 %cmp2, label %CC, label %DD 12 | 13 | CC: 14 | br label %DD 15 | 16 | DD: 17 | ret i32 %a 18 | } 19 | 20 | -------------------------------------------------------------------------------- /test/test_hello_pass_plugin.py: -------------------------------------------------------------------------------- 1 | import sys, unittest 2 | from tools import SamplesTestCase 3 | 4 | OUTPUT_HELLO_FUNCS = '''\ 5 | Hello: mult 6 | Hello: fact 7 | ''' 8 | 9 | class TestHelloPassPlugin(SamplesTestCase): 10 | def test_hello_on_fact(self): 11 | self.assertOptPluginOutput('hello_pass.so', ['-hello-funcs'], 'fact.ll', 12 | OUTPUT_HELLO_FUNCS) 13 | 14 | if __name__ == '__main__': 15 | unittest.main() 16 | -------------------------------------------------------------------------------- /using_clang_toolchain/exceptions1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void foo(int i) { 6 | if (i > 2) { 7 | throw std::runtime_error("Expected i <= 2"); 8 | } 9 | } 10 | 11 | int main(int argc, char **argv) { 12 | try { 13 | foo(argc); 14 | } catch (std::exception &e) { 15 | std::cerr << "Got exception: " << e.what() << std::endl; 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/all_tests.py: -------------------------------------------------------------------------------- 1 | import os, sys, unittest 2 | 3 | if not os.path.isdir('inputs') or not os.path.isdir('build'): 4 | print('ERROR: Please execute from the project root directory.') 5 | print('..... And build the samples first.') 6 | sys.exit(1) 7 | else: 8 | tests = unittest.TestLoader().discover('test', 'test*.py', 'test') 9 | result = unittest.TextTestRunner().run(tests) 10 | sys.exit(0 if result.wasSuccessful() else 1) 11 | -------------------------------------------------------------------------------- /inputs/namesp.cpp: -------------------------------------------------------------------------------- 1 | namespace Vroom { 2 | int kwa; 3 | 4 | int foobar(int i) { return i * 2; } 5 | 6 | constexpr double dodo(); 7 | 8 | float bar3(); 9 | double foo2(); 10 | 11 | float bolly(); 12 | 13 | struct Joe { 14 | double bar3(); 15 | }; 16 | }; 17 | 18 | int bolly(); 19 | 20 | namespace Swing { 21 | constexpr float juju = 2.0; 22 | 23 | float foobar(float i) { return i * 2; } 24 | 25 | using ::bolly; 26 | }; 27 | 28 | namespace blagonda { 29 | using Vroom::bolly; 30 | }; 31 | -------------------------------------------------------------------------------- /test/test_clang_check.py: -------------------------------------------------------------------------------- 1 | import os, sys, unittest 2 | from tools import run_exe 3 | 4 | 5 | class TestClangCheck(unittest.TestCase): 6 | def test_live(self): 7 | # basic smoke test 8 | exe = os.path.join('build', 'clang-check') 9 | input = os.path.join('inputs', 'fact.c') 10 | rc, stdout = run_exe(exe, ['-ast-print', input, '--']) 11 | self.assertTrue(stdout.startswith(b'unsigned int')) 12 | 13 | if __name__ == '__main__': 14 | unittest.main() 15 | -------------------------------------------------------------------------------- /inputs/types.c: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | double d; 3 | char c; 4 | unsigned i; 5 | char ar[10]; 6 | } mystruct; 7 | 8 | void *cpy(void *dest, const void *src, unsigned n); 9 | 10 | void structadder(mystruct a, mystruct b, mystruct *out) { 11 | mystruct ss; 12 | ss.d = a.d + b.d; 13 | ss.c = a.c + b.c; 14 | ss.i = a.i + b.i; 15 | for (int i = 0; i < b.i; ++i) { 16 | ss.ar[i] = a.ar[i] + b.ar[i]; 17 | } 18 | out[13].ar[2] += 1; 19 | cpy(out, &ss, sizeof(mystruct)); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /test/test_simple_module_pass.py: -------------------------------------------------------------------------------- 1 | import sys, unittest 2 | from tools import SamplesTestCase 3 | 4 | 5 | OUTPUT_FOR_GLOBALS = '''\ 6 | Found global named "gfloat": type = float* 7 | Found global named "gppfloat": type = float*** 8 | Found global named "gint": type = i32* 9 | ''' 10 | 11 | PROG = 'simple_module_pass' 12 | 13 | class TestSimpleModulePass(SamplesTestCase): 14 | def test_on_globals(self): 15 | self.assertSampleOutput([PROG], 'globals.ll', OUTPUT_FOR_GLOBALS) 16 | 17 | if __name__ == '__main__': 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /inputs/assert.cc: -------------------------------------------------------------------------------- 1 | extern "C" void __assertfail( 2 | const void *message, 3 | const void *file, 4 | unsigned int line, 5 | const void *function, 6 | unsigned long charsize); 7 | 8 | void __assert_fail( 9 | const char *__assertion, 10 | const char *__file, 11 | unsigned int __line, 12 | const char *__function) 13 | { 14 | __assertfail( 15 | (const void *)__assertion, 16 | (const void *)__file, 17 | __line, 18 | (const void *)__function, 19 | sizeof(char)); 20 | } 21 | -------------------------------------------------------------------------------- /inputs/using_builtins.c: -------------------------------------------------------------------------------- 1 | // This code uses printf without declaring. 2 | // 3 | // This will emit a warning and produce a declaration for the builtin 4 | // implicitly: 5 | // 6 | // clang -cc1 -emit-llvm inputs/using_builtins.c 7 | // 8 | // It will also produce a warning about mismatch in %d format with 'f' argument. 9 | // 10 | // This (C++ mode) will error, because in C++ such implicit declarations are not 11 | // legal: 12 | // 13 | // clang -cc1 -x c++ -emit-llvm inputs/using_builtins.c 14 | // 15 | 16 | void foo(int i, float f) { 17 | printf("%d %f\n", f, f); 18 | } 19 | -------------------------------------------------------------------------------- /test/test_rewriter_sample.py: -------------------------------------------------------------------------------- 1 | import os, sys, unittest 2 | from tools import SamplesTestCase 3 | 4 | OUTPUT = '''\ 5 | // Begin function foo returning void 6 | void foo(int* a, int *b) { 7 | if (a[0] > 1) // the 'if' part 8 | { 9 | b[0] = 2; 10 | } 11 | } 12 | // End function foo 13 | 14 | void bar(float x, float y); // just a declaration 15 | ''' 16 | 17 | PROG = 'rewritersample' 18 | 19 | class TestRewriterSample(SamplesTestCase): 20 | def test_live(self): 21 | self.assertSampleOutput([PROG], 'cfunc_with_if.c', OUTPUT) 22 | 23 | if __name__ == '__main__': 24 | unittest.main() 25 | -------------------------------------------------------------------------------- /test/test_tooling_sample.py: -------------------------------------------------------------------------------- 1 | import os, sys, unittest 2 | from tools import SamplesTestCase 3 | 4 | OUTPUT = '''\ 5 | // Begin function foo returning void 6 | void foo(int* a, int *b) { 7 | if (a[0] > 1) // the 'if' part 8 | { 9 | b[0] = 2; 10 | } 11 | } 12 | // End function foo 13 | 14 | void bar(float x, float y); // just a declaration 15 | ''' 16 | 17 | PROG = 'tooling_sample' 18 | 19 | class TestToolingSample(SamplesTestCase): 20 | def test_live(self): 21 | self.assertClangToolOutput([PROG], 'cfunc_with_if.c', OUTPUT) 22 | 23 | if __name__ == '__main__': 24 | unittest.main() 25 | -------------------------------------------------------------------------------- /using_clang_toolchain/memmain.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void* memcpy_caller(void* dst, const void* src, size_t n); 4 | void* memmove_caller(void* dst, const void* src, size_t n); 5 | void* memset_caller(void* dst, int c, size_t n); 6 | 7 | int main(int argc, char** argv) { 8 | const size_t N = 256; 9 | char buf[N]; 10 | 11 | for (size_t i = 0; i < N; ++i) { 12 | buf[i] = i; 13 | } 14 | 15 | memmove_caller(&buf[4], &buf[0], 0); 16 | //memmove_caller(&buf[1], &buf[5], 0); 17 | 18 | for (size_t i = 0; i < 30; ++i) { 19 | printf("0x%x ", buf[i]); 20 | } 21 | printf("\n"); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /inputs/loopy-cfg.ll: -------------------------------------------------------------------------------- 1 | ; Has a number of distinct loops in an otherwise simple graph 2 | 3 | define i32 @func(i32 %a, i32 %b) #0 { 4 | AA: 5 | %cmp1 = icmp eq i32 %a, %b 6 | br i1 %cmp1, label %BB, label %CC 7 | 8 | BB: 9 | br label %BB1 10 | 11 | BB1: 12 | br label %BB2 13 | 14 | BB2: 15 | %cmp4 = icmp eq i32 %a, %b 16 | br i1 %cmp4, label %BB3, label %BB 17 | 18 | BB3: 19 | br label %BB4 20 | 21 | BB4: 22 | %cmp3 = icmp eq i32 %a, %b 23 | br i1 %cmp3, label %BB3, label %CC 24 | 25 | CC: 26 | br label %CC1 27 | 28 | CC1: 29 | br label %CC2 30 | 31 | CC2: 32 | %cmp2 = icmp eq i32 %a, %b 33 | br i1 %cmp2, label %DD, label %CC 34 | 35 | DD: 36 | ret i32 %a 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/test_simple_bb_pass.py: -------------------------------------------------------------------------------- 1 | import sys, unittest 2 | from tools import SamplesTestCase 3 | 4 | 5 | OUTPUT_FOR_FACT = '''\ 6 | i32 size 32 bits 7 | i32 size 32 bits 8 | i32 size 32 bits 9 | i32 size 32 bits 10 | i32 size 32 bits 11 | i32 size 32 bits 12 | ''' 13 | 14 | OUTPUT_FOR_TYPES = '''\ 15 | %struct.mystruct = type { double, i8, i32, [10 x i8] } size 256 bits 16 | ''' 17 | 18 | PROG = 'simple_bb_pass' 19 | 20 | class TestSimpleBBPass(SamplesTestCase): 21 | def test_on_fact(self): 22 | self.assertSampleOutput([PROG], 'fact.ll', OUTPUT_FOR_FACT) 23 | 24 | def test_on_types(self): 25 | self.assertSampleOutput([PROG], 'types.ll', OUTPUT_FOR_TYPES) 26 | 27 | if __name__ == '__main__': 28 | unittest.main() 29 | -------------------------------------------------------------------------------- /inputs/cuda_support_header.h: -------------------------------------------------------------------------------- 1 | /* Minimal declarations for CUDA support. Testing purposes only. */ 2 | 3 | #define __constant__ __attribute__((constant)) 4 | #define __device__ __attribute__((device)) 5 | #define __global__ __attribute__((global)) 6 | #define __host__ __attribute__((host)) 7 | #define __shared__ __attribute__((shared)) 8 | #define __launch_bounds__(...) __attribute__((launch_bounds(__VA_ARGS__))) 9 | 10 | struct dim3 { 11 | unsigned x, y, z; 12 | __host__ __device__ dim3(unsigned x, unsigned y = 1, unsigned z = 1) : x(x), y(y), z(z) {} 13 | }; 14 | 15 | typedef struct cudaStream *cudaStream_t; 16 | 17 | int cudaConfigureCall(dim3 gridSize, dim3 blockSize, unsigned sharedSize = 0, 18 | cudaStream_t stream = 0); 19 | -------------------------------------------------------------------------------- /src_clang/experimental/showattrs.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | import sys 3 | import clang.cindex 4 | from clang.cindex import CursorKind 5 | 6 | def visitor(cursor): 7 | children = list(cursor.get_children()) 8 | 9 | for child in children: 10 | if (cursor.kind == CursorKind.FUNCTION_DECL and 11 | child.kind == CursorKind.CUDAGLOBAL_ATTR): 12 | print 'Function {0} is CUDA global!'.format(cursor.displayname) 13 | 14 | visitor(child) 15 | 16 | index = clang.cindex.Index.create() 17 | # Parse as CUDA 18 | tu = index.parse(sys.argv[1], args=['-x', 'cuda']) 19 | 20 | diagnostics = list(tu.diagnostics) 21 | if len(diagnostics) > 0: 22 | print 'There were parse errors' 23 | pprint.pprint(diagnostics) 24 | else: 25 | visitor(tu.cursor) 26 | -------------------------------------------------------------------------------- /inputs/kernel-signatures.c: -------------------------------------------------------------------------------- 1 | // Due to the special attributes, this file should be analyzed by Clang in CUDA 2 | // mode. For example, dump the AST with: 3 | // 4 | // $ clang-check inputs/kernel-signatures.c -ast-dump -- -xcuda 5 | // 6 | 7 | __attribute__((global)) void ker1(float* farr, double* darr, int n) { 8 | } 9 | 10 | __attribute__((device)) void notakernel(int n, float* f1) { 11 | } 12 | 13 | typedef int* intptr; 14 | 15 | __attribute__((global)) void ker2(unsigned* uarr, intptr iarr) { 16 | } 17 | 18 | void foobar() { 19 | } 20 | 21 | 22 | template 23 | void bazinga(T* k) { 24 | } 25 | 26 | int booga, chuppa; 27 | 28 | struct St { 29 | int b; 30 | 31 | void joe(int ii, float ff) { 32 | bazinga(&ii); 33 | bazinga(&ff); 34 | } 35 | }; 36 | 37 | 38 | -------------------------------------------------------------------------------- /src_clang/experimental/callexpr.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | import sys 3 | import clang.cindex 4 | 5 | def visitor(cursor): 6 | print 'visiting', cursor.kind 7 | if cursor.kind == clang.cindex.CursorKind.CALL_EXPR: 8 | print 'Found %s [line=%s, col=%s]' % ( 9 | cursor.displayname, cursor.location.line, cursor.location.column) 10 | 11 | children = list(cursor.get_children()) 12 | print ' has {0} children'.format(len(children)) 13 | for child in children: 14 | visitor(child) 15 | 16 | index = clang.cindex.Index.create() 17 | # Parse as C++ 18 | tu = index.parse(sys.argv[1], args=['-x', 'c++']) 19 | 20 | diagnostics = list(tu.diagnostics) 21 | if len(diagnostics) > 0: 22 | print 'There were parse errors' 23 | pprint.pprint(diagnostics) 24 | else: 25 | visitor(tu.cursor) 26 | -------------------------------------------------------------------------------- /tools/sample-js.js: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | ... 10 | ... 11 | 12 |
13 | TranslationUnitDecl 0x3511670 <<invalid sloc>> <invalid sloc>
14 | 
15 | -------------------------------------------------------------------------------- /tools/template.html: -------------------------------------------------------------------------------- 1 | 2 | 39 | 40 | 41 | 42 | 43 | hello
44 | hello 45 | 46 |
47 | 48 | 49 | 50 | TranslationUnitDecl 0x38a3670 implicit 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /inputs/threadidx.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3 | target triple = "x86_64-unknown-linux-gnu" 4 | 5 | %struct.uint3 = type { i32, i32, i32 } 6 | 7 | @threadIdx = external constant %struct.uint3 8 | 9 | ; Function Attrs: nounwind readnone uwtable 10 | define i32 @foo(i32 %a, i32 %b) #0 { 11 | entry: 12 | %0 = load i32* getelementptr inbounds (%struct.uint3* @threadIdx, i64 0, i32 1), align 4, !tbaa !1 13 | %cmp = icmp ugt i32 %0, 5 14 | %a.b = select i1 %cmp, i32 %a, i32 %b 15 | ret i32 %a.b 16 | } 17 | 18 | attributes #0 = { nounwind readnone uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 19 | 20 | !llvm.ident = !{!0} 21 | 22 | !0 = !{!"clang version 3.5 "} 23 | !1 = !{!2, !3, i64 4} 24 | !2 = !{!"", !3, i64 0, !3, i64 4, !3, i64 8} 25 | !3 = !{!"int", !4, i64 0} 26 | !4 = !{!"omnipotent char", !5, i64 0} 27 | !5 = !{!"Simple C/C++ TBAA"} 28 | -------------------------------------------------------------------------------- /src_clang/experimental/show-mangle.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | import sys 3 | import clang.cindex 4 | 5 | def get_cursor(source, spelling): 6 | """Obtain a cursor from a source object. 7 | 8 | This provides a convenient search mechanism to find a cursor with specific 9 | spelling within a source. The first argument can be either a 10 | TranslationUnit or Cursor instance. 11 | 12 | If the cursor is not found, None is returned. 13 | """ 14 | # Convenience for calling on a TU. 15 | 16 | root_cursor = (source if isinstance(source, clang.cindex.Cursor) 17 | else source.cursor) 18 | 19 | for cursor in root_cursor.walk_preorder(): 20 | if cursor.spelling == spelling: 21 | return cursor 22 | 23 | return None 24 | 25 | src = '''\ 26 | int foo(int, int); 27 | ''' 28 | 29 | tu = clang.cindex.TranslationUnit.from_source('t.cpp', 30 | ['-x', 'c++'], 31 | unsaved_files=[('t.cpp', src)]) 32 | 33 | foo = get_cursor(tu, 'foo') 34 | 35 | print(foo.mangled_name) 36 | -------------------------------------------------------------------------------- /using_clang_toolchain/memcaller.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void* memcpy_impl(void* dst, const void* src, size_t n) { 4 | unsigned char* d = dst; 5 | const unsigned char* s = src; 6 | for (size_t i = 0; i < n; ++i) { 7 | d[i] = s[i]; 8 | } 9 | return dst; 10 | } 11 | 12 | void* memmove_impl(void* dst, const void* src, size_t n) { 13 | unsigned char* d = dst; 14 | const unsigned char* s = src; 15 | if (s < d) { 16 | while (n--) { 17 | d[n] = s[n]; 18 | } 19 | } else { 20 | for (size_t i = 0; i < n; ++i) { 21 | d[i] = s[i]; 22 | } 23 | } 24 | return dst; 25 | } 26 | 27 | void* memcpy_caller(void* dst, const void* src, size_t n) { 28 | return memcpy(dst, src, n); 29 | //return memcpy_impl(dst, src, n); 30 | } 31 | 32 | void* memcpy_caller_casting(int* dst, const int* src, size_t n) { 33 | return memcpy(dst, src, n); 34 | } 35 | 36 | void* memmove_caller(void* dst, const void* src, size_t n) { 37 | //return memmove(dst, src, n); 38 | return memmove_impl(dst, src, n); 39 | } 40 | 41 | void* memset_caller(void* dst, int c, size_t n) { 42 | return memset(dst, c, n); 43 | } 44 | -------------------------------------------------------------------------------- /inputs/ctor-initializer-list.cpp: -------------------------------------------------------------------------------- 1 | namespace detail { 2 | 3 | struct Base {}; 4 | 5 | constexpr int foo2(int i) { return 2 * i; } 6 | } 7 | 8 | namespace ns { 9 | 10 | // constexpr int foo2(int i) { 11 | // return 2*i; 12 | //} 13 | 14 | using detail::foo2; 15 | 16 | constexpr float foo2(float f) { return 2.2 + f; } 17 | 18 | float joe = foo2(45.4f); 19 | 20 | namespace Sambusak { 21 | 22 | constexpr double foo2(double d) { return d * 2.2; } 23 | } 24 | } 25 | 26 | int iii = ns::foo2(10); 27 | float fla = ns::foo2(4.4f); 28 | double dla = ns::Sambusak::foo2(4.4); 29 | 30 | void bbbb() { 31 | auto func = ns::Sambusak::foo2; 32 | int k = func(10); 33 | } 34 | 35 | template class Foo : public detail::Base { 36 | public: 37 | typedef typename T::zoo_type arg_type; 38 | 39 | Foo(char c) : iguana(c) { f = 0.9; } 40 | 41 | Foo(arg_type i_, float f_) : kak(i_), iguana(ns::foo2(i_)), f(f_) {} 42 | Foo(arg_type i_, float f_, int tt) { 43 | using ns::foo2; 44 | iguana = foo2(i_, i_); 45 | } 46 | 47 | Foo() : detail::Base(), iguana(1) {} 48 | 49 | private: 50 | int kak; 51 | int iguana; 52 | float f; 53 | 54 | struct Faborz { 55 | } faborz; 56 | }; 57 | -------------------------------------------------------------------------------- /src_clang/experimental/kernel-sigs.py: -------------------------------------------------------------------------------- 1 | import pprint 2 | import sys 3 | import clang.cindex 4 | from clang.cindex import CursorKind 5 | 6 | 7 | def handle_function_decl(fdecl_cursor): 8 | children = list(fdecl_cursor.get_children()) 9 | 10 | # Only interested in functions that have a CUDAGLOBAL_ATTR attached. 11 | if not any(c.kind == CursorKind.CUDAGLOBAL_ATTR for c in children): 12 | return 13 | 14 | print fdecl_cursor.displayname 15 | 16 | # Look at param decls 17 | for c in children: 18 | if c.kind == CursorKind.PARM_DECL: 19 | print '>> param "{0}" with type "{1}" [{2}, canonical = {3}]'.format( 20 | c.spelling, c.type.spelling, c.type.kind.name, 21 | c.type.get_canonical().spelling) 22 | 23 | 24 | index = clang.cindex.Index.create() 25 | # Parse as CUDA 26 | tu = index.parse(sys.argv[1], args=['-x', 'cuda']) 27 | 28 | diagnostics = list(tu.diagnostics) 29 | if len(diagnostics) > 0: 30 | print 'There were parse errors' 31 | pprint.pprint(diagnostics) 32 | else: 33 | for c in tu.cursor.walk_preorder(): 34 | if c.kind == CursorKind.FUNCTION_DECL: 35 | handle_function_decl(c) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /test/test_bb_toposort_sccs.py: -------------------------------------------------------------------------------- 1 | import sys, unittest 2 | from tools import SamplesTestCase 3 | 4 | OUTPUT_DIAMOND_TOPO = '''\ 5 | Topological sort of func: 6 | AA 7 | BB 8 | CC 9 | DD 10 | ''' 11 | 12 | OUTPUT_DIAMOND_PO = '''\ 13 | Basic blocks of func in post-order: 14 | DD 15 | CC 16 | BB 17 | AA 18 | ''' 19 | 20 | OUTPUT_LOOPY_TOPO = '''\ 21 | Topological sort of func: 22 | Detected cycle: edge from BB4 to BB3 23 | Sorting failed 24 | ''' 25 | 26 | OUTPUT_LOOPY_SCC = '''\ 27 | SCCs for func in post-order: 28 | SCC: DD 29 | SCC: CC2 CC1 CC 30 | SCC: BB4 BB3 31 | SCC: BB2 BB1 BB 32 | SCC: AA 33 | ''' 34 | 35 | PROG = 'bb_toposort_sccs' 36 | 37 | class TestBBToposortSCCS(SamplesTestCase): 38 | def test_topo_on_diamond(self): 39 | self.assertSampleOutput([PROG, '-topo'], 'diamond-cfg.ll', OUTPUT_DIAMOND_TOPO) 40 | 41 | def test_po_on_diamond(self): 42 | self.assertSampleOutput([PROG, '-po'], 'diamond-cfg.ll', OUTPUT_DIAMOND_PO) 43 | 44 | def test_topo_on_loopy(self): 45 | self.assertSampleOutput([PROG, '-topo'], 'loopy-cfg.ll', OUTPUT_LOOPY_TOPO) 46 | 47 | def test_scc_on_loopy(self): 48 | self.assertSampleOutput([PROG, '-scc'], 'loopy-cfg.ll', OUTPUT_LOOPY_SCC) 49 | 50 | if __name__ == '__main__': 51 | unittest.main() 52 | -------------------------------------------------------------------------------- /inputs/globals.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = '' 2 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3 | target triple = "x86_64-unknown-linux-gnu" 4 | 5 | @gfloat = common global float 0.000000e+00, align 4 6 | @gppfloat = common global float** null, align 8 7 | @gint = common global i32 0, align 4 8 | 9 | ; Function Attrs: nounwind readonly uwtable 10 | define float @foo() #0 { 11 | entry: 12 | %0 = load float, float* @gfloat, align 4, !tbaa !1 13 | %1 = load float**, float*** @gppfloat, align 8, !tbaa !5 14 | %2 = load float*, float** %1, align 8, !tbaa !5 15 | %3 = load float, float* %2, align 4, !tbaa !1 16 | %add = fadd float %0, %3 17 | ret float %add 18 | } 19 | 20 | attributes #0 = { nounwind readonly uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 21 | 22 | !llvm.ident = !{!0} 23 | 24 | !0 = !{!"clang version 3.7.0 (http://llvm.org/git/clang 805ac0a233be64ffeeff2334db1873760c1588e9) (http://llvm.org/git/llvm.git 5109ec06a641f039775e1a6bcd7d50bb04dbb8f6)"} 25 | !1 = !{!2, !2, i64 0} 26 | !2 = !{!"float", !3, i64 0} 27 | !3 = !{!"omnipotent char", !4, i64 0} 28 | !4 = !{!"Simple C/C++ TBAA"} 29 | !5 = !{!6, !6, i64 0} 30 | !6 = !{!"any pointer", !3, i64 0} 31 | -------------------------------------------------------------------------------- /tools/show-cfg.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------- 2 | # Script for showing the CFG of the given LLVM IR file. 3 | # 'dot' must be installed. If 'eog' is installed, it's popped to show the 4 | # produced image. 5 | # 6 | # Eli Bendersky (eliben@gmail.com) 7 | # This code is in the public domain 8 | #------------------------------------------------------------------------------- 9 | import os, re, subprocess, sys 10 | import tempfile 11 | import os.path 12 | 13 | LLVMDIR = os.path.expanduser('~/llvm/build/svn-make-debug/Debug+Asserts/bin') 14 | OPT = os.path.join(LLVMDIR, 'opt') 15 | 16 | def show_dot(filename): 17 | outpng = os.path.join(tempfile.gettempdir(), filename + '.png') 18 | subprocess.check_call(['dot', '-Tpng', filename, '-o', outpng]) 19 | print('Created', outpng, '... Running eog') 20 | subprocess.call('eog ' + outpng + ' &', shell=True) 21 | 22 | def main(): 23 | opt_out = subprocess.check_output( 24 | [OPT, '-dot-cfg-only', '-disable-output', sys.argv[1]], 25 | stderr=subprocess.STDOUT) # opt prints stuff to stderr too o_O 26 | for line in opt_out.decode('utf-8').splitlines(): 27 | m = re.search("Writing '(cfg\.[^\.]+\.dot)", line) 28 | if m: 29 | show_dot(m.group(1)) 30 | else: 31 | print('Cannot parse line:', line) 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /inputs/twodoublefoo.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'inputs/twodoublefoo.c' 2 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3 | target triple = "x86_64-unknown-linux-gnu" 4 | 5 | ; Function Attrs: nounwind readnone uwtable 6 | define double @foo(double %a, double %b) #0 { 7 | %1 = fmul double %a, 2.000000e+00 8 | %2 = fadd double %1, %b 9 | ret double %2 10 | } 11 | 12 | ; Function Attrs: nounwind readnone uwtable 13 | define double @bar(double %a, double %b) #0 { 14 | %1 = tail call fastcc double @internal(double %a, double %b) 15 | %2 = fmul double %1, 1.000000e+01 16 | ret double %2 17 | } 18 | 19 | ; Function Attrs: noinline nounwind readnone uwtable 20 | define internal fastcc double @internal(double %a, double %b) #1 { 21 | %1 = fmul double %a, %b 22 | ret double %1 23 | } 24 | 25 | attributes #0 = { nounwind readnone uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } 26 | attributes #1 = { noinline nounwind readnone uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } 27 | 28 | !llvm.ident = !{!0} 29 | 30 | !0 = !{!"clang version 3.7.0 (tags/RELEASE_370/final)"} 31 | -------------------------------------------------------------------------------- /src_llvm/access_debug_metadata.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // This is currently ad-hoc 3 | // 4 | // Eli Bendersky (eliben@gmail.com) 5 | // This code is in the public domain 6 | //------------------------------------------------------------------------------ 7 | #include "llvm/IR/Metadata.h" 8 | #include "llvm/IR/Module.h" 9 | #include "llvm/IRReader/IRReader.h" 10 | #include "llvm/Pass.h" 11 | #include "llvm/Support/SourceMgr.h" 12 | #include "llvm/Support/raw_ostream.h" 13 | 14 | using namespace llvm; 15 | 16 | int main(int argc, char **argv) { 17 | if (argc < 2) { 18 | errs() << "Usage: " << argv[0] << " \n"; 19 | return 1; 20 | } 21 | 22 | // Parse the input LLVM IR file into a module. 23 | SMDiagnostic Err; 24 | LLVMContext Context; 25 | std::unique_ptr Mod(parseIRFile(argv[1], Err, Context)); 26 | if (!Mod) { 27 | Err.print(argv[0], errs()); 28 | return 1; 29 | } 30 | 31 | // Go over all named mdnodes in the module 32 | for (Module::const_named_metadata_iterator I = Mod->named_metadata_begin(), 33 | E = Mod->named_metadata_end(); 34 | I != E; ++I) { 35 | outs() << "Found MDNode:\n"; 36 | // These dumps only work with LLVM built with a special cmake flag enabling 37 | // dumps. 38 | // I->dump(); 39 | 40 | for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { 41 | Metadata *Op = I->getOperand(i); 42 | if (auto *N = dyn_cast(Op)) { 43 | outs() << " Has MDNode operand:\n "; 44 | // N->dump(); 45 | outs() << " " << N->getNumOperands() << " operands\n"; 46 | } 47 | } 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /src_llvm/hello_pass.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // hello_pass LLVM sample. Demonstrates: 3 | // 4 | // * Creating a "plugin" pass loaded dynamically by opt. 5 | // * Implementing getAnalysisUsage to notify the pass manager about possible 6 | // interactions with other passes. 7 | // 8 | // Once the .so is built, it can be loaded by opt. For example: 9 | // 10 | // $ opt -load build/hello_pass.so -hello-funcs > /dev/null 11 | // 12 | // Taken from the LLVM distribution with some modifications. LLVM's license 13 | // applies. 14 | //------------------------------------------------------------------------------ 15 | #include "llvm/IR/Function.h" 16 | #include "llvm/Pass.h" 17 | #include "llvm/Support/raw_ostream.h" 18 | 19 | using namespace llvm; 20 | 21 | // HelloFuncs - emit the names of functions encountered. 22 | struct HelloFuncs : public FunctionPass { 23 | HelloFuncs() : FunctionPass(ID) {} 24 | 25 | virtual bool runOnFunction(Function &F) { 26 | outs() << "Hello: "; 27 | outs().write_escaped(F.getName()) << '\n'; 28 | return false; 29 | } 30 | 31 | // We don't modify the program, so we preserve all analyses. 32 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 33 | AU.setPreservesAll(); 34 | } 35 | 36 | // The address of this member is used to uniquely identify the class. This is 37 | // used by LLVM's own RTTI mechanism. 38 | static char ID; 39 | }; 40 | 41 | char HelloFuncs::ID = 0; 42 | 43 | // Register our pass with the pass manager in opt. For more information, see: 44 | // http://llvm.org/docs/WritingAnLLVMPass.html 45 | static RegisterPass 46 | X("hello-funcs", "Hello World Pass (with getAnalysisUsage implemented)"); 47 | -------------------------------------------------------------------------------- /src_llvm/experimental/loop_info.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Experimental sample; use at your own peril. 3 | // 4 | // Eli Bendersky (eliben@gmail.com) 5 | // This code is in the public domain 6 | //------------------------------------------------------------------------------ 7 | #include "llvm/ADT/DenseMap.h" 8 | #include "llvm/ADT/PostOrderIterator.h" 9 | #include "llvm/Analysis/LoopInfo.h" 10 | #include "llvm/IR/DataLayout.h" 11 | #include "llvm/IR/Instruction.h" 12 | #include "llvm/IR/Instructions.h" 13 | #include "llvm/IR/LegacyPassManager.h" 14 | #include "llvm/IR/Module.h" 15 | #include "llvm/IRReader/IRReader.h" 16 | #include "llvm/Pass.h" 17 | #include "llvm/Support/SourceMgr.h" 18 | #include "llvm/Support/raw_ostream.h" 19 | #include 20 | #include 21 | 22 | using namespace llvm; 23 | 24 | class AnalyzeLoops : public FunctionPass { 25 | public: 26 | AnalyzeLoops() : FunctionPass(ID) {} 27 | 28 | void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); } 29 | 30 | virtual bool runOnFunction(Function &F) { 31 | LoopInfo &LI = getAnalysis(); 32 | for (LoopInfo::iterator L = LI.begin(), LE = LI.end(); L != LE; ++L) { 33 | (*L)->dump(); 34 | } 35 | return false; 36 | } 37 | 38 | static char ID; 39 | }; 40 | 41 | char AnalyzeLoops::ID = 0; 42 | 43 | int main(int argc, char **argv) { 44 | if (argc < 2) { 45 | errs() << "Usage: " << argv[0] << " \n"; 46 | return 1; 47 | } 48 | 49 | // Parse the input LLVM IR file into a module. 50 | SMDiagnostic Err; 51 | LLVMContext Context; 52 | std::unique_ptr Mod(parseIRFile(argv[1], Err, Context)); 53 | if (!Mod) { 54 | Err.print(argv[0], errs()); 55 | return 1; 56 | } 57 | 58 | // Create a pass manager and fill it with the passes we want to run. 59 | PassManager PM; 60 | PM.add(new LoopInfo()); 61 | PM.add(new AnalyzeLoops()); 62 | PM.run(*Mod); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tools/gen_c_straightline.py: -------------------------------------------------------------------------------- 1 | """Run with --numops= to customize the size of the output. 2 | 3 | Emits the function to stdout. 4 | """ 5 | import argparse 6 | import random 7 | 8 | FUNC_TEMPLATE = '''\ 9 | void foo(const int* in1, const int* in2, int* out) {{ 10 | {func_body} 11 | }} 12 | ''' 13 | 14 | 15 | def main(): 16 | argparser = argparse.ArgumentParser() 17 | argparser.add_argument('--numops', type=int, default=20) 18 | args = argparser.parse_args() 19 | 20 | numops = args.numops 21 | bodylines = [] 22 | 23 | def emit_new_temp(n): 24 | bodylines.append(' int temp{0};'.format(n)) 25 | 26 | def emit_op(dest, inputs): 27 | line = ' {0} = '.format(dest) 28 | for n, inp in enumerate(inputs): 29 | line += inp 30 | if n < len(inputs) - 1: 31 | line += ' {0} '.format(random.choice(('+', '-', '*', '/', '%'))) 32 | line += ';' 33 | bodylines.append(line) 34 | 35 | ntemps = 2 36 | emit_new_temp(0) 37 | emit_new_temp(1) 38 | 39 | for i in range(numops): 40 | # Decide on the destination. 50% chance it goes to out, 50% to new 41 | # temporary. 42 | if random.random() > 0.5: 43 | dest = 'out[{0}]'.format(random.randint(0, numops)) 44 | else: 45 | emit_new_temp(ntemps) 46 | dest = 'temp{0}'.format(ntemps) 47 | ntemps += 1 48 | 49 | # Decide how many inputs it will have and where they come from (in1, in2 50 | # or temporaries) 51 | num_inputs = random.randint(2, 6) 52 | inputs = [] 53 | for ni in range(num_inputs): 54 | choice = random.random() 55 | if choice > 0.8: 56 | inp = 'in1[{0}]'.format(random.randint(0, numops)) 57 | elif choice > 0.6: 58 | inp = 'in2[{0}]'.format(random.randint(0, numops)) 59 | else: 60 | # pick temp num at random 61 | inp = 'temp{0}'.format(random.randint(0, ntemps - 1)) 62 | inputs.append(inp) 63 | emit_op(dest, inputs) 64 | 65 | print(FUNC_TEMPLATE.format(func_body='\n'.join(bodylines))) 66 | 67 | 68 | if __name__ == '__main__': 69 | main() 70 | -------------------------------------------------------------------------------- /inputs/typeuse.cpp: -------------------------------------------------------------------------------- 1 | namespace Frob { 2 | 3 | template struct Homer { T a, b; }; 4 | } 5 | 6 | using namespace Frob; 7 | 8 | Homer h; 9 | 10 | void foobar(Frob::Homer hh) {} 11 | 12 | template void templated() { T t; } 13 | 14 | void joe() { 15 | templated>(); 16 | 17 | int i[] = {10, 20}; 18 | Homer *h = reinterpret_cast *>(i); 19 | } 20 | 21 | template struct scalar_multiple2_op {}; 22 | 23 | template class CwiseUnaryOp {}; 24 | 25 | inline const CwiseUnaryOp>, float> 26 | operator*(const Homer &scalar) const {} 27 | 28 | // template 29 | // class Container { 30 | // T t; 31 | // Homer ht; 32 | // }; 33 | 34 | // template 35 | // class Container, U> { 36 | // }; 37 | 38 | // template <> 39 | // class Container, int> {}; 40 | 41 | // template <> 42 | // class Container, float> {} ; 43 | 44 | // /** Overloaded for efficient real matrix times complex scalar value */ 45 | // EIGEN_DEVICE_FUNC 46 | // inline const 47 | // CwiseUnaryOp >, 48 | // const Derived> operator*(const std::complex& scalar) const 49 | // { 50 | // return 51 | // CwiseUnaryOp >, 52 | // const Derived> 53 | // (*static_cast(this), 54 | // internal::scalar_multiple2_op >(scalar)); 55 | // } 56 | 57 | // template 58 | // struct scalar_multiple2_op { 59 | // typedef typename scalar_product_traits::ReturnType 60 | // result_type; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 61 | // scalar_multiple2_op(const scalar_multiple2_op& other) : 62 | // m_other(other.m_other) { } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 63 | // scalar_multiple2_op(const Scalar2& other) : m_other(other) { } 64 | // EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const 65 | // Scalar1& a) const { return a * m_other; } typename 66 | // add_const_on_value_type::Nested>::type m_other; 67 | // }; 68 | -------------------------------------------------------------------------------- /src_llvm/simple_module_pass.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // simple_module_pass LLVM sample. Demonstrates: 3 | // 4 | // * How to write a ModulePass 5 | // * How to iterate over the global values in a module, and access their names 6 | // and types. 7 | // * How to produce a string representation of a LLVM type. 8 | // 9 | // Eli Bendersky (eliben@gmail.com) 10 | // This code is in the public domain 11 | //------------------------------------------------------------------------------ 12 | #include "llvm/IR/LegacyPassManager.h" 13 | #include "llvm/IR/Module.h" 14 | #include "llvm/IRReader/IRReader.h" 15 | #include "llvm/Pass.h" 16 | #include "llvm/Support/SourceMgr.h" 17 | #include "llvm/Support/raw_ostream.h" 18 | 19 | using namespace llvm; 20 | 21 | // Helper method for converting the name of a LLVM type to a string 22 | static std::string LLVMTypeAsString(const Type *T) { 23 | std::string TypeName; 24 | raw_string_ostream N(TypeName); 25 | T->print(N); 26 | return N.str(); 27 | } 28 | 29 | class GVNames : public ModulePass { 30 | public: 31 | GVNames() : ModulePass(ID) {} 32 | 33 | virtual bool runOnModule(Module &M) { 34 | for (Module::const_global_iterator GI = M.global_begin(), 35 | GE = M.global_end(); 36 | GI != GE; ++GI) { 37 | outs() << "Found global named \"" << GI->getName() 38 | << "\": type = " << LLVMTypeAsString(GI->getType()) << "\n"; 39 | } 40 | return false; 41 | } 42 | 43 | // The address of this member is used to uniquely identify the class. This is 44 | // used by LLVM's own RTTI mechanism. 45 | static char ID; 46 | }; 47 | 48 | char GVNames::ID = 0; 49 | 50 | int main(int argc, char **argv) { 51 | if (argc < 2) { 52 | errs() << "Usage: " << argv[0] << " \n"; 53 | return 1; 54 | } 55 | 56 | // Parse the input LLVM IR file into a module. 57 | SMDiagnostic Err; 58 | LLVMContext Context; 59 | std::unique_ptr Mod(parseIRFile(argv[1], Err, Context)); 60 | if (!Mod) { 61 | Err.print(argv[0], errs()); 62 | return 1; 63 | } 64 | 65 | // Create a pass manager and fill it with the passes we want to run. 66 | legacy::PassManager PM; 67 | PM.add(new GVNames()); 68 | PM.run(*Mod); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /inputs/fact.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'fact.c' 2 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3 | target triple = "x86_64-unknown-linux-gnu" 4 | 5 | ; Function Attrs: nounwind 6 | define i32 @mult(i32 %a, i32 %b) #0 { 7 | %1 = alloca i32, align 4 8 | %2 = alloca i32, align 4 9 | %i = alloca i32, align 4 10 | %s = alloca i32, align 4 11 | store i32 %a, i32* %1, align 4 12 | store i32 %b, i32* %2, align 4 13 | store i32 0, i32* %s, align 4 14 | store i32 0, i32* %i, align 4 15 | br label %3 16 | 17 | ;