llrb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.gitmodules +4 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +56 -0
  8. data/README.md +311 -0
  9. data/Rakefile +30 -0
  10. data/bin/bm_app_fib +41 -0
  11. data/bin/bm_empty_method +33 -0
  12. data/bin/bm_loop_while +27 -0
  13. data/bin/bm_plus +33 -0
  14. data/bin/console +14 -0
  15. data/bin/loop_while.rb +5 -0
  16. data/bin/setup +8 -0
  17. data/ext/llrb/cfg.h +124 -0
  18. data/ext/llrb/compiler.c +987 -0
  19. data/ext/llrb/compiler/funcs.h +164 -0
  20. data/ext/llrb/compiler/stack.h +43 -0
  21. data/ext/llrb/cruby.h +42 -0
  22. data/ext/llrb/cruby/ccan/build_assert/build_assert.h +40 -0
  23. data/ext/llrb/cruby/ccan/check_type/check_type.h +63 -0
  24. data/ext/llrb/cruby/ccan/container_of/container_of.h +142 -0
  25. data/ext/llrb/cruby/ccan/list/list.h +773 -0
  26. data/ext/llrb/cruby/ccan/str/str.h +16 -0
  27. data/ext/llrb/cruby/internal.h +1774 -0
  28. data/ext/llrb/cruby/iseq.h +252 -0
  29. data/ext/llrb/cruby/method.h +213 -0
  30. data/ext/llrb/cruby/node.h +520 -0
  31. data/ext/llrb/cruby/probes_helper.h +43 -0
  32. data/ext/llrb/cruby/ruby_assert.h +54 -0
  33. data/ext/llrb/cruby/ruby_atomic.h +233 -0
  34. data/ext/llrb/cruby/thread_pthread.h +54 -0
  35. data/ext/llrb/cruby/vm_core.h +1646 -0
  36. data/ext/llrb/cruby/vm_debug.h +37 -0
  37. data/ext/llrb/cruby/vm_exec.h +182 -0
  38. data/ext/llrb/cruby/vm_opts.h +57 -0
  39. data/ext/llrb/cruby_extra/id.h +220 -0
  40. data/ext/llrb/cruby_extra/insns.inc +113 -0
  41. data/ext/llrb/cruby_extra/insns_info.inc +796 -0
  42. data/ext/llrb/cruby_extra/probes.h +80 -0
  43. data/ext/llrb/extconf.rb +102 -0
  44. data/ext/llrb/llrb.c +148 -0
  45. data/ext/llrb/optimizer.cc +118 -0
  46. data/ext/llrb/parser.c +191 -0
  47. data/ext/llrb/profiler.c +336 -0
  48. data/ext/llrb_insn_checkkeyword.c +20 -0
  49. data/ext/llrb_insn_checkmatch.c +28 -0
  50. data/ext/llrb_insn_concatarray.c +23 -0
  51. data/ext/llrb_insn_concatstrings.c +21 -0
  52. data/ext/llrb_insn_defined.c +9 -0
  53. data/ext/llrb_insn_getclassvariable.c +10 -0
  54. data/ext/llrb_insn_getinstancevariable.c +44 -0
  55. data/ext/llrb_insn_getlocal.c +14 -0
  56. data/ext/llrb_insn_getlocal_level0.c +8 -0
  57. data/ext/llrb_insn_getlocal_level1.c +8 -0
  58. data/ext/llrb_insn_getspecial.c +14 -0
  59. data/ext/llrb_insn_invokeblock.c +39 -0
  60. data/ext/llrb_insn_invokesuper.c +47 -0
  61. data/ext/llrb_insn_opt_aref.c +25 -0
  62. data/ext/llrb_insn_opt_aset.c +28 -0
  63. data/ext/llrb_insn_opt_div.c +32 -0
  64. data/ext/llrb_insn_opt_eq.c +57 -0
  65. data/ext/llrb_insn_opt_ge.c +28 -0
  66. data/ext/llrb_insn_opt_gt.c +38 -0
  67. data/ext/llrb_insn_opt_le.c +29 -0
  68. data/ext/llrb_insn_opt_lt.c +38 -0
  69. data/ext/llrb_insn_opt_ltlt.c +27 -0
  70. data/ext/llrb_insn_opt_minus.c +36 -0
  71. data/ext/llrb_insn_opt_mod.c +32 -0
  72. data/ext/llrb_insn_opt_mult.c +30 -0
  73. data/ext/llrb_insn_opt_neq.c +103 -0
  74. data/ext/llrb_insn_opt_plus.c +48 -0
  75. data/ext/llrb_insn_opt_send_without_block.c +45 -0
  76. data/ext/llrb_insn_opt_str_freeze.c +12 -0
  77. data/ext/llrb_insn_putspecialobject.c +23 -0
  78. data/ext/llrb_insn_send.c +49 -0
  79. data/ext/llrb_insn_setclassvariable.c +19 -0
  80. data/ext/llrb_insn_setconstant.c +23 -0
  81. data/ext/llrb_insn_setinstancevariable.c +48 -0
  82. data/ext/llrb_insn_setlocal.c +16 -0
  83. data/ext/llrb_insn_setlocal_level0.c +9 -0
  84. data/ext/llrb_insn_setlocal_level1.c +10 -0
  85. data/ext/llrb_insn_setspecial.c +15 -0
  86. data/ext/llrb_insn_splatarray.c +13 -0
  87. data/ext/llrb_insn_throw.c +11 -0
  88. data/ext/llrb_insn_trace.c +37 -0
  89. data/ext/llrb_push_result.c +14 -0
  90. data/ext/llrb_self_from_cfp.c +12 -0
  91. data/ext/llrb_set_pc.c +8 -0
  92. data/lib/llrb.rb +2 -0
  93. data/lib/llrb/jit.rb +76 -0
  94. data/lib/llrb/start.rb +2 -0
  95. data/lib/llrb/version.rb +3 -0
  96. data/llrb.gemspec +48 -0
  97. data/wercker.yml +31 -0
  98. metadata +227 -0
@@ -0,0 +1,164 @@
1
+ /*
2
+ * compiler/funcs.h: External function declaration called by JIT-ed code.
3
+ * This header is used only by compiler.c.
4
+ * TODO: Automatically generate this from something.
5
+ */
6
+
7
+ #ifndef LLRB_COMPILER_FUNCS_H
8
+ #define LLRB_COMPILER_FUNCS_H
9
+
10
+ #include <string.h>
11
+ #include "ruby.h"
12
+ #include "llvm-c/BitReader.h"
13
+ #include "llvm-c/Linker.h"
14
+
15
+ #define LLRB_EXTERN_FUNC_MAX_ARGC 6
16
+ struct llrb_extern_func {
17
+ unsigned int return_type; // 0 = void, 32 = 32bit int, 64 = 64bit int
18
+ unsigned int argc;
19
+ unsigned int argv[LLRB_EXTERN_FUNC_MAX_ARGC]; // 0 = void, 32 = 32bit int, 64 = 64bit int
20
+ bool unlimited;
21
+ const char *name;
22
+ bool has_bc;
23
+ };
24
+
25
+ // TODO: support 32bit environment
26
+ static struct llrb_extern_func llrb_extern_funcs[] = {
27
+ { 64, 0, { 0 }, false, "rb_hash_new" },
28
+ { 64, 1, { 64 }, false, "llrb_insn_opt_str_freeze", true },
29
+ { 64, 1, { 64 }, false, "llrb_insn_putspecialobject", true },
30
+ { 64, 1, { 64 }, false, "llrb_self_from_cfp", true },
31
+ { 64, 1, { 64 }, false, "rb_ary_clear" },
32
+ { 64, 1, { 64 }, false, "rb_ary_resurrect" },
33
+ { 64, 1, { 64 }, false, "rb_gvar_get" },
34
+ { 64, 1, { 64 }, false, "rb_obj_as_string" },
35
+ { 64, 1, { 64 }, false, "rb_str_freeze" },
36
+ { 64, 1, { 64 }, false, "rb_str_resurrect" },
37
+ { 64, 1, { 64 }, true, "llrb_insn_concatstrings", true },
38
+ { 64, 1, { 64 }, true, "rb_ary_new_from_args" },
39
+ { 0, 2, { 64, 64 }, false, "llrb_insn_setspecial", true },
40
+ { 0, 2, { 64, 64 }, false, "llrb_push_result", true },
41
+ { 0, 2, { 64, 64 }, false, "llrb_set_pc", true },
42
+ { 64, 2, { 64, 32 }, false, "rb_reg_new_ary" },
43
+ { 64, 2, { 64, 64 }, false, "llrb_insn_concatarray", true },
44
+ { 64, 2, { 64, 64 }, false, "llrb_insn_getclassvariable", true },
45
+ { 64, 2, { 64, 64 }, false, "llrb_insn_getlocal_level0", true },
46
+ { 64, 2, { 64, 64 }, false, "llrb_insn_getlocal_level1", true },
47
+ { 64, 2, { 64, 64 }, false, "llrb_insn_getspecial", true },
48
+ //{ 64, 2, { 64, 64 }, false, "llrb_insn_opt_newarray_max", true },
49
+ //{ 64, 2, { 64, 64 }, false, "llrb_insn_opt_newarray_min", true },
50
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_mult", true },
51
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_div", true },
52
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_mod", true },
53
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_eq", true },
54
+ { 64, 6, { 64, 64, 64, 64, 64, 64 }, false, "llrb_insn_opt_neq", true },
55
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_le", true },
56
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_gt", true },
57
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_ge", true },
58
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_ltlt", true },
59
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_aref", true },
60
+ { 64, 3, { 64, 64, 64 }, false, "llrb_insn_opt_aset", true },
61
+ { 64, 3, { 64, 64, 64 }, false, "llrb_insn_getinstancevariable", true },
62
+ { 0, 4, { 64, 64, 64, 64 }, false, "llrb_insn_setinstancevariable", true },
63
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_lt", true },
64
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_minus", true },
65
+ { 64, 2, { 64, 64 }, false, "llrb_insn_opt_plus", true },
66
+ { 64, 2, { 64, 64 }, false, "llrb_insn_splatarray", true },
67
+ { 64, 2, { 64, 64 }, false, "rb_gvar_set" },
68
+ { 64, 2, { 64, 64 }, false, "rb_ivar_get" },
69
+ { 64, 2, { 64, 64 }, true, "llrb_insn_toregexp" },
70
+ { 64, 2, { 64, 64 }, true, "rb_funcall" },
71
+ { 0, 3, { 64, 64, 64 }, false, "llrb_insn_setclassvariable", true },
72
+ { 0, 3, { 64, 64, 64 }, false, "llrb_insn_setlocal_level0", true },
73
+ { 0, 3, { 64, 64, 64 }, false, "llrb_insn_setlocal_level1", true },
74
+ { 64, 3, { 64, 64, 64 }, false, "llrb_insn_checkkeyword", true },
75
+ { 64, 3, { 64, 64, 64 }, false, "llrb_insn_checkmatch", true },
76
+ { 64, 3, { 64, 64, 64 }, false, "llrb_insn_getlocal", true },
77
+ { 64, 3, { 64, 64, 64 }, false, "rb_hash_aset" },
78
+ { 64, 3, { 64, 64, 64 }, false, "rb_ivar_set" },
79
+ { 64, 3, { 64, 64, 64 }, false, "rb_range_new" },
80
+ { 0, 4, { 64, 64, 32, 64 }, false, "llrb_insn_trace", true },
81
+ { 0, 4, { 64, 64, 64, 64 }, false, "llrb_insn_setconstant", true },
82
+ { 0, 4, { 64, 64, 64, 64 }, false, "llrb_insn_setlocal", true },
83
+ { 0, 4, { 64, 64, 64, 64 }, false, "llrb_insn_throw", true },
84
+ { 64, 4, { 64, 64, 64, 32 }, false, "vm_get_ev_const" },
85
+ { 64, 4, { 64, 64, 64, 32 }, true, "llrb_insn_invokeblock", true },
86
+ { 64, 4, { 64, 64, 64, 64 }, false, "llrb_insn_defined", true },
87
+ { 64, 5, { 64, 64, 64, 64, 32 }, true, "llrb_insn_opt_send_without_block", true },
88
+ { 64, 6, { 64, 64, 64, 64, 64, 32 }, true, "llrb_insn_invokesuper", true },
89
+ { 64, 6, { 64, 64, 64, 64, 64, 32 }, true, "llrb_insn_send", true },
90
+ };
91
+ static size_t llrb_extern_func_num = sizeof(llrb_extern_funcs) / sizeof(struct llrb_extern_func);
92
+
93
+ static inline LLVMTypeRef
94
+ llrb_num_to_type(unsigned int num)
95
+ {
96
+ switch (num) {
97
+ case 64:
98
+ return LLVMInt64Type();
99
+ case 32:
100
+ return LLVMInt32Type();
101
+ case 0:
102
+ return LLVMVoidType();
103
+ default:
104
+ rb_raise(rb_eCompileError, "'%d' is unexpected for llrb_num_to_type", num);
105
+ }
106
+ }
107
+
108
+ static void
109
+ llrb_link_module(LLVMModuleRef mod, const char *funcname)
110
+ {
111
+ char *bc_name = ZALLOC_N(char, strlen(LLRB_BITCODE_DIR "/") + strlen(funcname) + strlen(".bc") + 1); // freed in this function
112
+ strcat(bc_name, LLRB_BITCODE_DIR "/");
113
+ strcat(bc_name, funcname);
114
+ strcat(bc_name, ".bc");
115
+
116
+ LLVMMemoryBufferRef buf;
117
+ char *err;
118
+ if (LLVMCreateMemoryBufferWithContentsOfFile(bc_name, &buf, &err)) {
119
+ fprintf(stderr, "Failed to load func bitcode: '%s'\n", bc_name);
120
+ rb_raise(rb_eCompileError, "LLVMCreateMemoryBufferWithContentsOfFile Error: %s", err);
121
+ }
122
+ xfree(bc_name);
123
+
124
+ LLVMModuleRef func_mod;
125
+ if (LLVMParseBitcode2(buf, &func_mod)) {
126
+ rb_raise(rb_eCompileError, "LLVMParseBitcode2 Failed!");
127
+ }
128
+ LLVMDisposeMemoryBuffer(buf);
129
+
130
+ LLVMLinkModules2(mod, func_mod);
131
+ }
132
+
133
+ static LLVMValueRef
134
+ llrb_get_function(LLVMModuleRef mod, const char *name)
135
+ {
136
+ LLVMValueRef func = LLVMGetNamedFunction(mod, name);
137
+ if (func) return func;
138
+
139
+ for (size_t i = 0; i < llrb_extern_func_num; i++) {
140
+ if (strcmp(name, llrb_extern_funcs[i].name)) continue;
141
+
142
+ if (llrb_extern_funcs[i].has_bc) {
143
+ llrb_link_module(mod, llrb_extern_funcs[i].name);
144
+ func = LLVMGetNamedFunction(mod, name);
145
+ if (func) {
146
+ return func;
147
+ } else {
148
+ rb_raise(rb_eCompileError, "'%s' was not found in bitcode file", name);
149
+ }
150
+ }
151
+
152
+ LLVMTypeRef arg_types[LLRB_EXTERN_FUNC_MAX_ARGC];
153
+ for (unsigned int j = 0; j < llrb_extern_funcs[i].argc; j++) {
154
+ arg_types[j] = llrb_num_to_type(llrb_extern_funcs[i].argv[j]);
155
+ }
156
+ return LLVMAddFunction(mod, llrb_extern_funcs[i].name, LLVMFunctionType(
157
+ llrb_num_to_type(llrb_extern_funcs[i].return_type), arg_types,
158
+ llrb_extern_funcs[i].argc, llrb_extern_funcs[i].unlimited));
159
+ }
160
+
161
+ rb_raise(rb_eCompileError, "'%s' is not defined in llrb_extern_funcs", name);
162
+ }
163
+
164
+ #endif // LLRB_COMPILER_FUNCS_H
@@ -0,0 +1,43 @@
1
+ /*
2
+ * compiler/stack.h: Data structure to emulate YARV stack.
3
+ * This header is used only by compiler.c.
4
+ */
5
+
6
+ #ifndef LLRB_COMPILER_STACK_H
7
+ #define LLRB_COMPILER_STACK_H
8
+
9
+ // Emulates rb_control_frame's sp (stack pointer), which is function local
10
+ struct llrb_stack {
11
+ unsigned int size;
12
+ unsigned int max;
13
+ LLVMValueRef *body;
14
+ };
15
+
16
+ static void
17
+ llrb_stack_push(struct llrb_stack *stack, LLVMValueRef value)
18
+ {
19
+ if (stack->size >= stack->max) {
20
+ rb_raise(rb_eCompileError, "LLRB's internal stack overflow: max=%d, next size=%d", stack->max, stack->size+1);
21
+ }
22
+ stack->body[stack->size] = value;
23
+ stack->size++;
24
+ }
25
+
26
+ static LLVMValueRef
27
+ llrb_stack_pop(struct llrb_stack *stack)
28
+ {
29
+ if (stack->size <= 0) {
30
+ rb_raise(rb_eCompileError, "LLRB's internal stack underflow: next size=%d", stack->size-1);
31
+ }
32
+ stack->size--;
33
+ return stack->body[stack->size];
34
+ }
35
+
36
+ static inline LLVMValueRef
37
+ llrb_stack_topn(struct llrb_stack *stack, unsigned int n)
38
+ {
39
+ unsigned int last = stack->size - 1;
40
+ return stack->body[last - n];
41
+ }
42
+
43
+ #endif // LLRB_COMPILER_STACK_H
@@ -0,0 +1,42 @@
1
+ /*
2
+ * cruby.h: Has CRuby's internal data structure definitions including ISeq struct.
3
+ */
4
+
5
+ #ifndef LLRB_CRUBY_H
6
+ #define LLRB_CRUBY_H
7
+
8
+ #ifdef __clang__
9
+ # pragma clang diagnostic push
10
+ # pragma clang diagnostic ignored "-Wignored-attributes"
11
+ # pragma clang diagnostic ignored "-Wunknown-attributes"
12
+ #endif
13
+ #include "ruby.h"
14
+ #ifdef __clang__
15
+ # pragma clang diagnostic pop
16
+ #endif
17
+
18
+ #pragma GCC diagnostic push
19
+ #pragma GCC diagnostic ignored "-Wpedantic"
20
+ #include "cruby/internal.h"
21
+ #include "cruby/vm_core.h"
22
+ #pragma GCC diagnostic pop
23
+
24
+ #include "cruby/method.h"
25
+ #include "cruby/vm_exec.h"
26
+ #include "cruby/iseq.h"
27
+
28
+ /* start vm_insnhelper.h (which can't be compiled without calling static function) */
29
+
30
+ /* optimize insn */
31
+ #define FIXNUM_2_P(a, b) ((a) & (b) & 1)
32
+ #if USE_FLONUM
33
+ #define FLONUM_2_P(a, b) (((((a)^2) | ((b)^2)) & 3) == 0) /* (FLONUM_P(a) && FLONUM_P(b)) */
34
+ #else
35
+ #define FLONUM_2_P(a, b) 0
36
+ #endif
37
+
38
+ #define GET_PREV_EP(ep) ((VALUE *)((ep)[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03))
39
+
40
+ /* end vm_insnhelper.h */
41
+
42
+ #endif // LLRB_CRUBY_H
@@ -0,0 +1,40 @@
1
+ /* CC0 (Public domain) - see ccan/licenses/CC0 file for details */
2
+ #ifndef CCAN_BUILD_ASSERT_H
3
+ #define CCAN_BUILD_ASSERT_H
4
+
5
+ /**
6
+ * BUILD_ASSERT - assert a build-time dependency.
7
+ * @cond: the compile-time condition which must be true.
8
+ *
9
+ * Your compile will fail if the condition isn't true, or can't be evaluated
10
+ * by the compiler. This can only be used within a function.
11
+ *
12
+ * Example:
13
+ * #include <stddef.h>
14
+ * ...
15
+ * static char *foo_to_char(struct foo *foo)
16
+ * {
17
+ * // This code needs string to be at start of foo.
18
+ * BUILD_ASSERT(offsetof(struct foo, string) == 0);
19
+ * return (char *)foo;
20
+ * }
21
+ */
22
+ #define BUILD_ASSERT(cond) \
23
+ do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
24
+
25
+ /**
26
+ * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
27
+ * @cond: the compile-time condition which must be true.
28
+ *
29
+ * Your compile will fail if the condition isn't true, or can't be evaluated
30
+ * by the compiler. This can be used in an expression: its value is "0".
31
+ *
32
+ * Example:
33
+ * #define foo_to_char(foo) \
34
+ * ((char *)(foo) \
35
+ * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
36
+ */
37
+ #define BUILD_ASSERT_OR_ZERO(cond) \
38
+ (sizeof(char [1 - 2*!(cond)]) - 1)
39
+
40
+ #endif /* CCAN_BUILD_ASSERT_H */
@@ -0,0 +1,63 @@
1
+ /* CC0 (Public domain) - see ccan/licenses/CC0 file for details */
2
+ #ifndef CCAN_CHECK_TYPE_H
3
+ #define CCAN_CHECK_TYPE_H
4
+
5
+ /**
6
+ * check_type - issue a warning or build failure if type is not correct.
7
+ * @expr: the expression whose type we should check (not evaluated).
8
+ * @type: the exact type we expect the expression to be.
9
+ *
10
+ * This macro is usually used within other macros to try to ensure that a macro
11
+ * argument is of the expected type. No type promotion of the expression is
12
+ * done: an unsigned int is not the same as an int!
13
+ *
14
+ * check_type() always evaluates to 0.
15
+ *
16
+ * If your compiler does not support typeof, then the best we can do is fail
17
+ * to compile if the sizes of the types are unequal (a less complete check).
18
+ *
19
+ * Example:
20
+ * // They should always pass a 64-bit value to _set_some_value!
21
+ * #define set_some_value(expr) \
22
+ * _set_some_value((check_type((expr), uint64_t), (expr)))
23
+ */
24
+
25
+ /**
26
+ * check_types_match - issue a warning or build failure if types are not same.
27
+ * @expr1: the first expression (not evaluated).
28
+ * @expr2: the second expression (not evaluated).
29
+ *
30
+ * This macro is usually used within other macros to try to ensure that
31
+ * arguments are of identical types. No type promotion of the expressions is
32
+ * done: an unsigned int is not the same as an int!
33
+ *
34
+ * check_types_match() always evaluates to 0.
35
+ *
36
+ * If your compiler does not support typeof, then the best we can do is fail
37
+ * to compile if the sizes of the types are unequal (a less complete check).
38
+ *
39
+ * Example:
40
+ * // Do subtraction to get to enclosing type, but make sure that
41
+ * // pointer is of correct type for that member.
42
+ * #define container_of(mbr_ptr, encl_type, mbr) \
43
+ * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
44
+ * ((encl_type *) \
45
+ * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
46
+ */
47
+ #if HAVE_TYPEOF
48
+ #define check_type(expr, type) \
49
+ ((typeof(expr) *)0 != (type *)0)
50
+
51
+ #define check_types_match(expr1, expr2) \
52
+ ((typeof(expr1) *)0 != (typeof(expr2) *)0)
53
+ #else
54
+ #include "ccan/build_assert/build_assert.h"
55
+ /* Without typeof, we can only test the sizes. */
56
+ #define check_type(expr, type) \
57
+ BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
58
+
59
+ #define check_types_match(expr1, expr2) \
60
+ BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
61
+ #endif /* HAVE_TYPEOF */
62
+
63
+ #endif /* CCAN_CHECK_TYPE_H */
@@ -0,0 +1,142 @@
1
+ /* CC0 (Public domain) - see ccan/licenses/CC0 file for details */
2
+ #ifndef CCAN_CONTAINER_OF_H
3
+ #define CCAN_CONTAINER_OF_H
4
+ #include "ccan/check_type/check_type.h"
5
+
6
+ /**
7
+ * container_of - get pointer to enclosing structure
8
+ * @member_ptr: pointer to the structure member
9
+ * @containing_type: the type this member is within
10
+ * @member: the name of this member within the structure.
11
+ *
12
+ * Given a pointer to a member of a structure, this macro does pointer
13
+ * subtraction to return the pointer to the enclosing type.
14
+ *
15
+ * Example:
16
+ * struct foo {
17
+ * int fielda, fieldb;
18
+ * // ...
19
+ * };
20
+ * struct info {
21
+ * int some_other_field;
22
+ * struct foo my_foo;
23
+ * };
24
+ *
25
+ * static struct info *foo_to_info(struct foo *foo)
26
+ * {
27
+ * return container_of(foo, struct info, my_foo);
28
+ * }
29
+ */
30
+ #define container_of(member_ptr, containing_type, member) \
31
+ ((containing_type *) \
32
+ ((char *)(member_ptr) \
33
+ - container_off(containing_type, member)) \
34
+ + check_types_match(*(member_ptr), ((containing_type *)0)->member))
35
+
36
+
37
+ /**
38
+ * container_of_or_null - get pointer to enclosing structure, or NULL
39
+ * @member_ptr: pointer to the structure member
40
+ * @containing_type: the type this member is within
41
+ * @member: the name of this member within the structure.
42
+ *
43
+ * Given a pointer to a member of a structure, this macro does pointer
44
+ * subtraction to return the pointer to the enclosing type, unless it
45
+ * is given NULL, in which case it also returns NULL.
46
+ *
47
+ * Example:
48
+ * struct foo {
49
+ * int fielda, fieldb;
50
+ * // ...
51
+ * };
52
+ * struct info {
53
+ * int some_other_field;
54
+ * struct foo my_foo;
55
+ * };
56
+ *
57
+ * static struct info *foo_to_info_allowing_null(struct foo *foo)
58
+ * {
59
+ * return container_of_or_null(foo, struct info, my_foo);
60
+ * }
61
+ */
62
+ static inline char *container_of_or_null_(void *member_ptr, size_t offset)
63
+ {
64
+ return member_ptr ? (char *)member_ptr - offset : NULL;
65
+ }
66
+ #define container_of_or_null(member_ptr, containing_type, member) \
67
+ ((containing_type *) \
68
+ container_of_or_null_(member_ptr, \
69
+ container_off(containing_type, member)) \
70
+ + check_types_match(*(member_ptr), ((containing_type *)0)->member))
71
+
72
+ /**
73
+ * container_off - get offset to enclosing structure
74
+ * @containing_type: the type this member is within
75
+ * @member: the name of this member within the structure.
76
+ *
77
+ * Given a pointer to a member of a structure, this macro does
78
+ * typechecking and figures out the offset to the enclosing type.
79
+ *
80
+ * Example:
81
+ * struct foo {
82
+ * int fielda, fieldb;
83
+ * // ...
84
+ * };
85
+ * struct info {
86
+ * int some_other_field;
87
+ * struct foo my_foo;
88
+ * };
89
+ *
90
+ * static struct info *foo_to_info(struct foo *foo)
91
+ * {
92
+ * size_t off = container_off(struct info, my_foo);
93
+ * return (void *)((char *)foo - off);
94
+ * }
95
+ */
96
+ #define container_off(containing_type, member) \
97
+ offsetof(containing_type, member)
98
+
99
+ /**
100
+ * container_of_var - get pointer to enclosing structure using a variable
101
+ * @member_ptr: pointer to the structure member
102
+ * @container_var: a pointer of same type as this member's container
103
+ * @member: the name of this member within the structure.
104
+ *
105
+ * Given a pointer to a member of a structure, this macro does pointer
106
+ * subtraction to return the pointer to the enclosing type.
107
+ *
108
+ * Example:
109
+ * static struct info *foo_to_i(struct foo *foo)
110
+ * {
111
+ * struct info *i = container_of_var(foo, i, my_foo);
112
+ * return i;
113
+ * }
114
+ */
115
+ #if HAVE_TYPEOF
116
+ #define container_of_var(member_ptr, container_var, member) \
117
+ container_of(member_ptr, typeof(*container_var), member)
118
+ #else
119
+ #define container_of_var(member_ptr, container_var, member) \
120
+ ((void *)((char *)(member_ptr) - \
121
+ container_off_var(container_var, member)))
122
+ #endif
123
+
124
+ /**
125
+ * container_off_var - get offset of a field in enclosing structure
126
+ * @container_var: a pointer to a container structure
127
+ * @member: the name of a member within the structure.
128
+ *
129
+ * Given (any) pointer to a structure and a its member name, this
130
+ * macro does pointer subtraction to return offset of member in a
131
+ * structure memory layout.
132
+ *
133
+ */
134
+ #if HAVE_TYPEOF
135
+ #define container_off_var(var, member) \
136
+ container_off(typeof(*var), member)
137
+ #else
138
+ #define container_off_var(var, member) \
139
+ ((const char *)&(var)->member - (const char *)(var))
140
+ #endif
141
+
142
+ #endif /* CCAN_CONTAINER_OF_H */