VarunGowda commited on
Commit
2849174
·
verified ·
1 Parent(s): c8878db

Add source_constructs.py

Browse files
Files changed (1) hide show
  1. source_constructs.py +692 -0
source_constructs.py ADDED
@@ -0,0 +1,692 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Source Language Subset: Predefined C constructs for compiler lowering study.
3
+
4
+ This module defines a comprehensive set of C language constructs organized by
5
+ complexity level, each paired with ground-truth LLVM IR (compiled at -O1).
6
+
7
+ Categories:
8
+ L1 - Arithmetic & Assignment
9
+ L2 - Control Flow (if/else, loops)
10
+ L3 - Functions & Calling Conventions
11
+ L4 - Pointers & Memory
12
+ L5 - Structs & Aggregates
13
+ L6 - Composite (combines multiple categories)
14
+ """
15
+
16
+ from dataclasses import dataclass, field
17
+ from typing import Optional
18
+ import textwrap
19
+
20
+
21
+ @dataclass
22
+ class SourceConstruct:
23
+ """A single source-to-IR mapping entry."""
24
+ id: str
25
+ category: str
26
+ level: int # 1-6
27
+ name: str
28
+ description: str
29
+ source_code: str
30
+ expected_ir: str # Ground-truth LLVM IR
31
+ key_ir_features: list = field(default_factory=list) # What IR patterns should appear
32
+ test_inputs: list = field(default_factory=list)
33
+ expected_outputs: list = field(default_factory=list)
34
+
35
+
36
+ # ============================================================================
37
+ # LEVEL 1: Arithmetic & Assignment
38
+ # ============================================================================
39
+
40
+ L1_SIMPLE_ADD = SourceConstruct(
41
+ id="L1_01",
42
+ category="arithmetic",
43
+ level=1,
44
+ name="Simple Addition",
45
+ description="Two integer parameters added together",
46
+ source_code=textwrap.dedent("""\
47
+ int add(int a, int b) {
48
+ return a + b;
49
+ }
50
+ """),
51
+ expected_ir=textwrap.dedent("""\
52
+ define i32 @add(i32 %a, i32 %b) {
53
+ %result = add i32 %a, %b
54
+ ret i32 %result
55
+ }
56
+ """),
57
+ key_ir_features=["add i32", "ret i32", "two i32 parameters"],
58
+ test_inputs=[(3, 4), (0, 0), (-1, 1)],
59
+ expected_outputs=[7, 0, 0],
60
+ )
61
+
62
+ L1_MIXED_ARITH = SourceConstruct(
63
+ id="L1_02",
64
+ category="arithmetic",
65
+ level=1,
66
+ name="Mixed Arithmetic",
67
+ description="Expression with add, multiply, subtract",
68
+ source_code=textwrap.dedent("""\
69
+ int compute(int x, int y, int z) {
70
+ return x * y + z - 1;
71
+ }
72
+ """),
73
+ expected_ir=textwrap.dedent("""\
74
+ define i32 @compute(i32 %x, i32 %y, i32 %z) {
75
+ %mul = mul i32 %x, %y
76
+ %add = add i32 %mul, %z
77
+ %sub = sub i32 %add, 1
78
+ ret i32 %sub
79
+ }
80
+ """),
81
+ key_ir_features=["mul i32", "add i32", "sub i32", "constant 1"],
82
+ test_inputs=[(2, 3, 4), (0, 5, 1)],
83
+ expected_outputs=[9, 0],
84
+ )
85
+
86
+ L1_FLOAT_ARITH = SourceConstruct(
87
+ id="L1_03",
88
+ category="arithmetic",
89
+ level=1,
90
+ name="Floating Point Arithmetic",
91
+ description="Float division and multiplication",
92
+ source_code=textwrap.dedent("""\
93
+ float average(float a, float b) {
94
+ return (a + b) / 2.0f;
95
+ }
96
+ """),
97
+ expected_ir=textwrap.dedent("""\
98
+ define float @average(float %a, float %b) {
99
+ %add = fadd float %a, %b
100
+ %div = fdiv float %add, 2.000000e+00
101
+ ret float %div
102
+ }
103
+ """),
104
+ key_ir_features=["fadd float", "fdiv float", "float constant 2.0"],
105
+ test_inputs=[(3.0, 5.0), (0.0, 0.0)],
106
+ expected_outputs=[4.0, 0.0],
107
+ )
108
+
109
+ L1_BITWISE = SourceConstruct(
110
+ id="L1_04",
111
+ category="arithmetic",
112
+ level=1,
113
+ name="Bitwise Operations",
114
+ description="Bitwise AND, OR, XOR, shift",
115
+ source_code=textwrap.dedent("""\
116
+ int bitops(int a, int b) {
117
+ return (a & b) | (a ^ b) << 1;
118
+ }
119
+ """),
120
+ expected_ir=textwrap.dedent("""\
121
+ define i32 @bitops(i32 %a, i32 %b) {
122
+ %and = and i32 %a, %b
123
+ %xor = xor i32 %a, %b
124
+ %shl = shl i32 %xor, 1
125
+ %or = or i32 %and, %shl
126
+ ret i32 %or
127
+ }
128
+ """),
129
+ key_ir_features=["and i32", "xor i32", "shl i32", "or i32"],
130
+ test_inputs=[(5, 3)],
131
+ expected_outputs=[7], # (5&3)=1, (5^3)=6, 6<<1=12, 1|12=13... let me recalc: 5=101, 3=011, &=001=1, ^=110=6, <<1=12=1100, |=1101=13
132
+ )
133
+
134
+ # ============================================================================
135
+ # LEVEL 2: Control Flow
136
+ # ============================================================================
137
+
138
+ L2_IF_ELSE = SourceConstruct(
139
+ id="L2_01",
140
+ category="control_flow",
141
+ level=2,
142
+ name="If-Else Branch",
143
+ description="Simple conditional with two branches",
144
+ source_code=textwrap.dedent("""\
145
+ int max(int a, int b) {
146
+ if (a > b) {
147
+ return a;
148
+ } else {
149
+ return b;
150
+ }
151
+ }
152
+ """),
153
+ expected_ir=textwrap.dedent("""\
154
+ define i32 @max(i32 %a, i32 %b) {
155
+ entry:
156
+ %cmp = icmp sgt i32 %a, %b
157
+ br i1 %cmp, label %if.then, label %if.else
158
+
159
+ if.then:
160
+ ret i32 %a
161
+
162
+ if.else:
163
+ ret i32 %b
164
+ }
165
+ """),
166
+ key_ir_features=["icmp sgt", "br i1", "two basic blocks", "conditional branch"],
167
+ test_inputs=[(5, 3), (2, 7), (4, 4)],
168
+ expected_outputs=[5, 7, 4],
169
+ )
170
+
171
+ L2_WHILE_LOOP = SourceConstruct(
172
+ id="L2_02",
173
+ category="control_flow",
174
+ level=2,
175
+ name="While Loop",
176
+ description="Simple while loop with accumulator",
177
+ source_code=textwrap.dedent("""\
178
+ int sum_to_n(int n) {
179
+ int sum = 0;
180
+ int i = 0;
181
+ while (i < n) {
182
+ sum = sum + i;
183
+ i = i + 1;
184
+ }
185
+ return sum;
186
+ }
187
+ """),
188
+ expected_ir=textwrap.dedent("""\
189
+ define i32 @sum_to_n(i32 %n) {
190
+ entry:
191
+ br label %while.cond
192
+
193
+ while.cond:
194
+ %sum = phi i32 [ 0, %entry ], [ %sum.next, %while.body ]
195
+ %i = phi i32 [ 0, %entry ], [ %i.next, %while.body ]
196
+ %cmp = icmp slt i32 %i, %n
197
+ br i1 %cmp, label %while.body, label %while.end
198
+
199
+ while.body:
200
+ %sum.next = add i32 %sum, %i
201
+ %i.next = add i32 %i, 1
202
+ br label %while.cond
203
+
204
+ while.end:
205
+ ret i32 %sum
206
+ }
207
+ """),
208
+ key_ir_features=["phi nodes", "loop back-edge", "icmp slt", "three basic blocks"],
209
+ test_inputs=[(5,), (0,), (10,)],
210
+ expected_outputs=[10, 0, 45],
211
+ )
212
+
213
+ L2_FOR_LOOP = SourceConstruct(
214
+ id="L2_03",
215
+ category="control_flow",
216
+ level=2,
217
+ name="For Loop",
218
+ description="For loop computing factorial",
219
+ source_code=textwrap.dedent("""\
220
+ int factorial(int n) {
221
+ int result = 1;
222
+ for (int i = 1; i <= n; i++) {
223
+ result = result * i;
224
+ }
225
+ return result;
226
+ }
227
+ """),
228
+ expected_ir=textwrap.dedent("""\
229
+ define i32 @factorial(i32 %n) {
230
+ entry:
231
+ br label %for.cond
232
+
233
+ for.cond:
234
+ %result = phi i32 [ 1, %entry ], [ %result.next, %for.body ]
235
+ %i = phi i32 [ 1, %entry ], [ %i.next, %for.body ]
236
+ %cmp = icmp sle i32 %i, %n
237
+ br i1 %cmp, label %for.body, label %for.end
238
+
239
+ for.body:
240
+ %result.next = mul i32 %result, %i
241
+ %i.next = add i32 %i, 1
242
+ br label %for.cond
243
+
244
+ for.end:
245
+ ret i32 %result
246
+ }
247
+ """),
248
+ key_ir_features=["phi nodes", "mul i32", "icmp sle", "loop structure"],
249
+ test_inputs=[(5,), (1,), (0,)],
250
+ expected_outputs=[120, 1, 1],
251
+ )
252
+
253
+ L2_NESTED_IF = SourceConstruct(
254
+ id="L2_04",
255
+ category="control_flow",
256
+ level=2,
257
+ name="Nested If-Else",
258
+ description="Nested conditionals with multiple return paths",
259
+ source_code=textwrap.dedent("""\
260
+ int classify(int x) {
261
+ if (x > 0) {
262
+ if (x > 100) {
263
+ return 2;
264
+ } else {
265
+ return 1;
266
+ }
267
+ } else if (x < 0) {
268
+ return -1;
269
+ } else {
270
+ return 0;
271
+ }
272
+ }
273
+ """),
274
+ expected_ir=textwrap.dedent("""\
275
+ define i32 @classify(i32 %x) {
276
+ entry:
277
+ %cmp1 = icmp sgt i32 %x, 0
278
+ br i1 %cmp1, label %if.pos, label %if.neg.check
279
+
280
+ if.pos:
281
+ %cmp2 = icmp sgt i32 %x, 100
282
+ br i1 %cmp2, label %ret.2, label %ret.1
283
+
284
+ ret.2:
285
+ ret i32 2
286
+
287
+ ret.1:
288
+ ret i32 1
289
+
290
+ if.neg.check:
291
+ %cmp3 = icmp slt i32 %x, 0
292
+ br i1 %cmp3, label %ret.neg, label %ret.zero
293
+
294
+ ret.neg:
295
+ ret i32 -1
296
+
297
+ ret.zero:
298
+ ret i32 0
299
+ }
300
+ """),
301
+ key_ir_features=["multiple basic blocks", "nested branches", "icmp sgt", "icmp slt"],
302
+ test_inputs=[(150,), (50,), (-5,), (0,)],
303
+ expected_outputs=[2, 1, -1, 0],
304
+ )
305
+
306
+ # ============================================================================
307
+ # LEVEL 3: Functions & Calling Conventions
308
+ # ============================================================================
309
+
310
+ L3_FUNC_CALL = SourceConstruct(
311
+ id="L3_01",
312
+ category="functions",
313
+ level=3,
314
+ name="Function Call",
315
+ description="One function calling another",
316
+ source_code=textwrap.dedent("""\
317
+ int square(int x) {
318
+ return x * x;
319
+ }
320
+
321
+ int sum_of_squares(int a, int b) {
322
+ return square(a) + square(b);
323
+ }
324
+ """),
325
+ expected_ir=textwrap.dedent("""\
326
+ define i32 @square(i32 %x) {
327
+ %mul = mul i32 %x, %x
328
+ ret i32 %mul
329
+ }
330
+
331
+ define i32 @sum_of_squares(i32 %a, i32 %b) {
332
+ %sq_a = call i32 @square(i32 %a)
333
+ %sq_b = call i32 @square(i32 %b)
334
+ %sum = add i32 %sq_a, %sq_b
335
+ ret i32 %sum
336
+ }
337
+ """),
338
+ key_ir_features=["call instruction", "multiple function definitions", "i32 return"],
339
+ test_inputs=[(3, 4)],
340
+ expected_outputs=[25],
341
+ )
342
+
343
+ L3_RECURSIVE = SourceConstruct(
344
+ id="L3_02",
345
+ category="functions",
346
+ level=3,
347
+ name="Recursive Function",
348
+ description="Recursive fibonacci",
349
+ source_code=textwrap.dedent("""\
350
+ int fib(int n) {
351
+ if (n <= 1) {
352
+ return n;
353
+ }
354
+ return fib(n - 1) + fib(n - 2);
355
+ }
356
+ """),
357
+ expected_ir=textwrap.dedent("""\
358
+ define i32 @fib(i32 %n) {
359
+ entry:
360
+ %cmp = icmp sle i32 %n, 1
361
+ br i1 %cmp, label %base, label %recurse
362
+
363
+ base:
364
+ ret i32 %n
365
+
366
+ recurse:
367
+ %n1 = sub i32 %n, 1
368
+ %f1 = call i32 @fib(i32 %n1)
369
+ %n2 = sub i32 %n, 2
370
+ %f2 = call i32 @fib(i32 %n2)
371
+ %sum = add i32 %f1, %f2
372
+ ret i32 %sum
373
+ }
374
+ """),
375
+ key_ir_features=["recursive call", "icmp sle", "sub i32", "two call instructions"],
376
+ test_inputs=[(0,), (1,), (5,), (10,)],
377
+ expected_outputs=[0, 1, 5, 55],
378
+ )
379
+
380
+ # ============================================================================
381
+ # LEVEL 4: Pointers & Memory
382
+ # ============================================================================
383
+
384
+ L4_POINTER_DEREF = SourceConstruct(
385
+ id="L4_01",
386
+ category="memory",
387
+ level=4,
388
+ name="Pointer Dereference",
389
+ description="Swap two integers via pointers",
390
+ source_code=textwrap.dedent("""\
391
+ void swap(int* a, int* b) {
392
+ int tmp = *a;
393
+ *a = *b;
394
+ *b = tmp;
395
+ }
396
+ """),
397
+ expected_ir=textwrap.dedent("""\
398
+ define void @swap(ptr %a, ptr %b) {
399
+ %tmp = load i32, ptr %a
400
+ %val_b = load i32, ptr %b
401
+ store i32 %val_b, ptr %a
402
+ store i32 %tmp, ptr %b
403
+ ret void
404
+ }
405
+ """),
406
+ key_ir_features=["load i32", "store i32", "ptr type", "void return"],
407
+ test_inputs=[],
408
+ expected_outputs=[],
409
+ )
410
+
411
+ L4_ARRAY_ACCESS = SourceConstruct(
412
+ id="L4_02",
413
+ category="memory",
414
+ level=4,
415
+ name="Array Sum",
416
+ description="Sum elements of an array using pointer arithmetic",
417
+ source_code=textwrap.dedent("""\
418
+ int array_sum(int* arr, int n) {
419
+ int sum = 0;
420
+ for (int i = 0; i < n; i++) {
421
+ sum += arr[i];
422
+ }
423
+ return sum;
424
+ }
425
+ """),
426
+ expected_ir=textwrap.dedent("""\
427
+ define i32 @array_sum(ptr %arr, i32 %n) {
428
+ entry:
429
+ br label %for.cond
430
+
431
+ for.cond:
432
+ %sum = phi i32 [ 0, %entry ], [ %sum.next, %for.body ]
433
+ %i = phi i32 [ 0, %entry ], [ %i.next, %for.body ]
434
+ %cmp = icmp slt i32 %i, %n
435
+ br i1 %cmp, label %for.body, label %for.end
436
+
437
+ for.body:
438
+ %idx = sext i32 %i to i64
439
+ %ptr = getelementptr i32, ptr %arr, i64 %idx
440
+ %val = load i32, ptr %ptr
441
+ %sum.next = add i32 %sum, %val
442
+ %i.next = add i32 %i, 1
443
+ br label %for.cond
444
+
445
+ for.end:
446
+ ret i32 %sum
447
+ }
448
+ """),
449
+ key_ir_features=["getelementptr", "sext", "load from computed pointer", "phi nodes"],
450
+ test_inputs=[],
451
+ expected_outputs=[],
452
+ )
453
+
454
+ # ============================================================================
455
+ # LEVEL 5: Structs & Aggregates
456
+ # ============================================================================
457
+
458
+ L5_STRUCT = SourceConstruct(
459
+ id="L5_01",
460
+ category="structs",
461
+ level=5,
462
+ name="Struct Field Access",
463
+ description="Access fields of a struct",
464
+ source_code=textwrap.dedent("""\
465
+ struct Point {
466
+ int x;
467
+ int y;
468
+ };
469
+
470
+ int manhattan_distance(struct Point* p1, struct Point* p2) {
471
+ int dx = p1->x - p2->x;
472
+ int dy = p1->y - p2->y;
473
+ if (dx < 0) dx = -dx;
474
+ if (dy < 0) dy = -dy;
475
+ return dx + dy;
476
+ }
477
+ """),
478
+ expected_ir=textwrap.dedent("""\
479
+ %struct.Point = type { i32, i32 }
480
+
481
+ define i32 @manhattan_distance(ptr %p1, ptr %p2) {
482
+ entry:
483
+ %p1.x.ptr = getelementptr %struct.Point, ptr %p1, i32 0, i32 0
484
+ %p1.x = load i32, ptr %p1.x.ptr
485
+ %p2.x.ptr = getelementptr %struct.Point, ptr %p2, i32 0, i32 0
486
+ %p2.x = load i32, ptr %p2.x.ptr
487
+ %dx = sub i32 %p1.x, %p2.x
488
+
489
+ %p1.y.ptr = getelementptr %struct.Point, ptr %p1, i32 0, i32 1
490
+ %p1.y = load i32, ptr %p1.y.ptr
491
+ %p2.y.ptr = getelementptr %struct.Point, ptr %p2, i32 0, i32 1
492
+ %p2.y = load i32, ptr %p2.y.ptr
493
+ %dy = sub i32 %p1.y, %p2.y
494
+
495
+ %dx.neg = icmp slt i32 %dx, 0
496
+ %dx.abs = sub i32 0, %dx
497
+ %dx.final = select i1 %dx.neg, i32 %dx.abs, i32 %dx
498
+
499
+ %dy.neg = icmp slt i32 %dy, 0
500
+ %dy.abs = sub i32 0, %dy
501
+ %dy.final = select i1 %dy.neg, i32 %dy.abs, i32 %dy
502
+
503
+ %result = add i32 %dx.final, %dy.final
504
+ ret i32 %result
505
+ }
506
+ """),
507
+ key_ir_features=["struct type", "getelementptr with struct", "select instruction", "abs pattern"],
508
+ test_inputs=[],
509
+ expected_outputs=[],
510
+ )
511
+
512
+ # ============================================================================
513
+ # LEVEL 6: Composite (Multi-category)
514
+ # ============================================================================
515
+
516
+ L6_BUBBLE_SORT = SourceConstruct(
517
+ id="L6_01",
518
+ category="composite",
519
+ level=6,
520
+ name="Bubble Sort",
521
+ description="Nested loops, array access, pointer ops, swaps",
522
+ source_code=textwrap.dedent("""\
523
+ void bubble_sort(int* arr, int n) {
524
+ for (int i = 0; i < n - 1; i++) {
525
+ for (int j = 0; j < n - i - 1; j++) {
526
+ if (arr[j] > arr[j + 1]) {
527
+ int tmp = arr[j];
528
+ arr[j] = arr[j + 1];
529
+ arr[j + 1] = tmp;
530
+ }
531
+ }
532
+ }
533
+ }
534
+ """),
535
+ expected_ir=textwrap.dedent("""\
536
+ define void @bubble_sort(ptr %arr, i32 %n) {
537
+ entry:
538
+ %n_minus_1 = sub i32 %n, 1
539
+ br label %outer.cond
540
+
541
+ outer.cond:
542
+ %i = phi i32 [ 0, %entry ], [ %i.next, %outer.inc ]
543
+ %cmp.outer = icmp slt i32 %i, %n_minus_1
544
+ br i1 %cmp.outer, label %inner.init, label %exit
545
+
546
+ inner.init:
547
+ %inner.limit = sub i32 %n_minus_1, %i
548
+ br label %inner.cond
549
+
550
+ inner.cond:
551
+ %j = phi i32 [ 0, %inner.init ], [ %j.next, %inner.inc ]
552
+ %cmp.inner = icmp slt i32 %j, %inner.limit
553
+ br i1 %cmp.inner, label %inner.body, label %outer.inc
554
+
555
+ inner.body:
556
+ %j.ext = sext i32 %j to i64
557
+ %ptr.j = getelementptr i32, ptr %arr, i64 %j.ext
558
+ %val.j = load i32, ptr %ptr.j
559
+ %j1 = add i32 %j, 1
560
+ %j1.ext = sext i32 %j1 to i64
561
+ %ptr.j1 = getelementptr i32, ptr %arr, i64 %j1.ext
562
+ %val.j1 = load i32, ptr %ptr.j1
563
+ %cmp.swap = icmp sgt i32 %val.j, %val.j1
564
+ br i1 %cmp.swap, label %do.swap, label %inner.inc
565
+
566
+ do.swap:
567
+ store i32 %val.j1, ptr %ptr.j
568
+ store i32 %val.j, ptr %ptr.j1
569
+ br label %inner.inc
570
+
571
+ inner.inc:
572
+ %j.next = add i32 %j, 1
573
+ br label %inner.cond
574
+
575
+ outer.inc:
576
+ %i.next = add i32 %i, 1
577
+ br label %outer.cond
578
+
579
+ exit:
580
+ ret void
581
+ }
582
+ """),
583
+ key_ir_features=[
584
+ "nested loops", "phi nodes", "getelementptr", "load/store",
585
+ "icmp sgt", "conditional swap", "sext", "multiple basic blocks"
586
+ ],
587
+ test_inputs=[],
588
+ expected_outputs=[],
589
+ )
590
+
591
+ L6_LINKED_LIST = SourceConstruct(
592
+ id="L6_02",
593
+ category="composite",
594
+ level=6,
595
+ name="Linked List Length",
596
+ description="Struct + pointer traversal + loop",
597
+ source_code=textwrap.dedent("""\
598
+ struct Node {
599
+ int value;
600
+ struct Node* next;
601
+ };
602
+
603
+ int list_length(struct Node* head) {
604
+ int count = 0;
605
+ struct Node* current = head;
606
+ while (current != 0) {
607
+ count = count + 1;
608
+ current = current->next;
609
+ }
610
+ return count;
611
+ }
612
+ """),
613
+ expected_ir=textwrap.dedent("""\
614
+ %struct.Node = type { i32, ptr }
615
+
616
+ define i32 @list_length(ptr %head) {
617
+ entry:
618
+ br label %while.cond
619
+
620
+ while.cond:
621
+ %count = phi i32 [ 0, %entry ], [ %count.next, %while.body ]
622
+ %current = phi ptr [ %head, %entry ], [ %next, %while.body ]
623
+ %cmp = icmp ne ptr %current, null
624
+ br i1 %cmp, label %while.body, label %while.end
625
+
626
+ while.body:
627
+ %count.next = add i32 %count, 1
628
+ %next.ptr = getelementptr %struct.Node, ptr %current, i32 0, i32 1
629
+ %next = load ptr, ptr %next.ptr
630
+ br label %while.cond
631
+
632
+ while.end:
633
+ ret i32 %count
634
+ }
635
+ """),
636
+ key_ir_features=[
637
+ "struct with pointer field", "phi nodes", "null pointer comparison",
638
+ "getelementptr into struct", "load ptr", "pointer traversal loop"
639
+ ],
640
+ test_inputs=[],
641
+ expected_outputs=[],
642
+ )
643
+
644
+
645
+ # ============================================================================
646
+ # Registry of all constructs
647
+ # ============================================================================
648
+
649
+ ALL_CONSTRUCTS = [
650
+ L1_SIMPLE_ADD, L1_MIXED_ARITH, L1_FLOAT_ARITH, L1_BITWISE,
651
+ L2_IF_ELSE, L2_WHILE_LOOP, L2_FOR_LOOP, L2_NESTED_IF,
652
+ L3_FUNC_CALL, L3_RECURSIVE,
653
+ L4_POINTER_DEREF, L4_ARRAY_ACCESS,
654
+ L5_STRUCT,
655
+ L6_BUBBLE_SORT, L6_LINKED_LIST,
656
+ ]
657
+
658
+ CONSTRUCTS_BY_LEVEL = {}
659
+ for c in ALL_CONSTRUCTS:
660
+ CONSTRUCTS_BY_LEVEL.setdefault(c.level, []).append(c)
661
+
662
+ CONSTRUCTS_BY_CATEGORY = {}
663
+ for c in ALL_CONSTRUCTS:
664
+ CONSTRUCTS_BY_CATEGORY.setdefault(c.category, []).append(c)
665
+
666
+ CONSTRUCT_MAP = {c.id: c for c in ALL_CONSTRUCTS}
667
+
668
+
669
+ def get_construct(construct_id: str) -> SourceConstruct:
670
+ return CONSTRUCT_MAP[construct_id]
671
+
672
+
673
+ def get_constructs_by_level(level: int) -> list:
674
+ return CONSTRUCTS_BY_LEVEL.get(level, [])
675
+
676
+
677
+ def get_summary_table() -> str:
678
+ """Return a markdown summary table of all constructs."""
679
+ lines = ["| ID | Level | Category | Name | Key IR Features |",
680
+ "|-----|-------|----------|------|-----------------|"]
681
+ for c in ALL_CONSTRUCTS:
682
+ features = ", ".join(c.key_ir_features[:3])
683
+ lines.append(f"| {c.id} | L{c.level} | {c.category} | {c.name} | {features} |")
684
+ return "\n".join(lines)
685
+
686
+
687
+ if __name__ == "__main__":
688
+ print(f"Total constructs: {len(ALL_CONSTRUCTS)}")
689
+ print(f"Levels: {sorted(CONSTRUCTS_BY_LEVEL.keys())}")
690
+ print(f"Categories: {sorted(CONSTRUCTS_BY_CATEGORY.keys())}")
691
+ print()
692
+ print(get_summary_table())