├── .gitignore ├── LICENSE ├── README.md ├── boehmgc.ll ├── build.sh ├── c ├── build.sh └── sample.c └── setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/f1eba3434761ebb9630fb0048500552f3405da03/Global/macos.gitignore 2 | 3 | *.DS_Store 4 | .AppleDouble 5 | .LSOverride 6 | 7 | # Icon must end with two \r 8 | Icon 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | .com.apple.timemachine.donotpresent 21 | 22 | # Directories potentially created on remote AFP share 23 | .AppleDB 24 | .AppleDesktop 25 | Network Trash Folder 26 | Temporary Items 27 | .apdisk 28 | 29 | boehmgc 30 | boehmgc.s 31 | c/*.ll 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Tatsuya Tanaka 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Example to use Boehm GC on LLVM IR. 2 | ==== 3 | 4 | see: [boehmgc.ll](https://github.com/tattn/llvm-boehmgc-sample/blob/master/boehmgc.ll) 5 | 6 | ```sh 7 | # build.sh 8 | 9 | BOEHMGC_VERSION=`brew list --versions boehmgc | awk '{print $2}'` 10 | BOEHMGC_PATH=/usr/local/Cellar/bdw-gc/$BOEHMGC_VERSION 11 | OUTPUT=boehmgc 12 | 13 | llc $OUTPUT.ll 14 | cc -I$BOEHMGC_PATH/include/ \ 15 | -L$BOEHMGC_PATH/lib/ -lgc \ 16 | -o $OUTPUT $OUTPUT.s 17 | ``` 18 | 19 | ```bash 20 | $ ./build.sh 21 | $ ./boehmgc 22 | 1234567890 23 | freed 0 24 | freed 1 25 | freed 2 26 | freed 3 27 | . 28 | . 29 | . 30 | freed 98 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /boehmgc.ll: -------------------------------------------------------------------------------- 1 | ; LLVM 4.0.0.1 @64bit 2 | ; created by tattn 3 | 4 | ; my_malloc 5 | 6 | define internal i8* @my_malloc(i64 %size) { 7 | %ret = call noalias i8* @GC_malloc(i64 %size) 8 | ret i8* %ret 9 | } 10 | 11 | ; finalizer 12 | 13 | @finalizer.str.freed = private unnamed_addr constant [10 x i8] c"freed %d\0A\00" 14 | @finalizer.count = internal global i32 0, align 4 15 | 16 | define internal void @finalizer(i8*, i8*) { 17 | %count = load i32, i32* @finalizer.count, align 4 18 | %count2 = add nsw i32 %count, 1 19 | store i32 %count2, i32* @finalizer.count, align 4 20 | call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @finalizer.str.freed, i32 0, i32 0), i32 %count) 21 | ret void 22 | } 23 | 24 | ; main 25 | 26 | @main.str.format = private constant [5 x i8] c"%ld\0A\00" 27 | 28 | define i32 @main() { 29 | call void @GC_init() 30 | 31 | %i8_int64 = call i8* @my_malloc(i64 8) 32 | %int64 = bitcast i8* %i8_int64 to i64* 33 | store i64 1234567890, i64* %int64 34 | %int64v = load i64, i64* %int64 35 | call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @main.str.format, i32 0, i32 0), i64 %int64v) 36 | 37 | 38 | %i = alloca i32, align 4 39 | %p = alloca i8*, align 8 40 | store i32 0, i32* %i, align 4 41 | 42 | 43 | br label %for_start 44 | 45 | for_start: 46 | %iv = load i32, i32* %i, align 4 47 | %for_cond = icmp slt i32 %iv, 100 48 | br i1 %for_cond, label %for_body, label %for_end 49 | 50 | for_body: 51 | %pv = call i8* @my_malloc(i64 128) 52 | store i8* %pv, i8** %p, align 8 53 | call void @GC_register_finalizer(i8* %pv, void (i8*, i8*)* @finalizer, i8* null, void (i8*, i8*)** null, i8** null) 54 | br label %for_next 55 | 56 | for_next: 57 | %iv2 = load i32, i32* %i, align 4 58 | %iv3 = add nsw i32 %iv2, 1 59 | store i32 %iv3, i32* %i, align 4 60 | br label %for_start 61 | 62 | for_end: 63 | call void @GC_gcollect() 64 | ret i32 0 65 | } 66 | 67 | ; decrlaration 68 | 69 | declare i32 @printf(i8*, ...) 70 | 71 | 72 | @GC_gc_no = external global i64, align 8 73 | declare void @GC_init() 74 | declare noalias i8* @GC_malloc(i64) 75 | declare i32 @GC_calloc(...) 76 | declare i8* @GC_realloc(i8*, i64) 77 | declare void @GC_free(i8*) 78 | declare void @GC_gcollect() 79 | declare void @GC_register_finalizer(i8*, void (i8*, i8*)*, i8*, void (i8*, i8*)**, i8**) 80 | declare void @GC_set_max_heap_size(i64) 81 | declare i64 @GC_size(i8*) 82 | declare i8* @GC_base(i8*) 83 | declare noalias i8* @GC_malloc_uncollectable(i64) 84 | declare i64 @GC_get_heap_size() 85 | declare i64 @GC_get_free_bytes() 86 | declare i64 @GC_get_bytes_since_gc() 87 | declare i64 @GC_get_total_bytes() 88 | 89 | 90 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | BOEHMGC_VERSION=`brew list --versions boehmgc | awk '{print $2}'` 2 | BOEHMGC_PATH=/usr/local/Cellar/bdw-gc/$BOEHMGC_VERSION 3 | 4 | OUTPUT=boehmgc 5 | llc $OUTPUT.ll 6 | cc -I$BOEHMGC_PATH/include/ \ 7 | -L$BOEHMGC_PATH/lib/ -lgc \ 8 | -o $OUTPUT $OUTPUT.s 9 | 10 | -------------------------------------------------------------------------------- /c/build.sh: -------------------------------------------------------------------------------- 1 | llvm-gcc -S -emit-llvm sample.c 2 | -------------------------------------------------------------------------------- /c/sample.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void* 5 | my_malloc(long size) { 6 | return GC_malloc(size); 7 | } 8 | 9 | static void 10 | finalizer(void* obj, void* client_data) 11 | { 12 | static int count = 0; 13 | printf("freed%d\n", count++); 14 | } 15 | 16 | int 17 | main(int argc, char* argv[]) 18 | { 19 | GC_init(); 20 | int i = 0; 21 | for (i = 0; i < 100; i++) { 22 | void* p = my_malloc(128); 23 | GC_register_finalizer(p, finalizer, NULL, NULL, NULL); 24 | } 25 | 26 | GC_gcollect(); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | brew install llvm 2 | brew install boehmgc 3 | 4 | echo 'please set llvm path' 5 | echo export PATH="/usr/local/opt/llvm/bin:\$PATH' 6 | --------------------------------------------------------------------------------