kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

123_spec_demo.toy (7280B)


      1 type Word = i64;
      2 type Fn1 = fn(Word): Word;
      3 
      4 record Node;
      5 
      6 record Pair {
      7   a: Word,
      8   b: Word,
      9 }
     10 
     11 record @[.packed] Header {
     12   tag: u8,
     13   len: u32,
     14 }
     15 
     16 record AlignedPair {
     17   first @[.align(16)]: i32,
     18   second: i32,
     19 }
     20 
     21 record Node {
     22   value: Word,
     23   next: *Node,
     24 }
     25 
     26 tuple Range {
     27   Word,
     28   Word,
     29 }
     30 
     31 enum Mode: i32 {
     32   .cold = 1,
     33   .warm = 2,
     34   .hot = 3,
     35 }
     36 
     37 extern fn imported_word(x: Word): Word;
     38 extern var @[.threadlocal, .tls_model(.local_exec)] imported_tls: i32;
     39 extern let imported_table: *u8;
     40 
     41 pub let answer: i32 = 42;
     42 pub let pi: f64 = 3.0;
     43 pub let msg: [6]u8 = "hi\n\x21\0\0";
     44 pub let numbers: [4]Word = [1, 2];
     45 pub var @[.common] tentative: Word;
     46 
     47 pub let pair_global: Pair = Pair { a: 4, b: 5 };
     48 pub let range_global: Range = Range { 10, 20 };
     49 pub var answer_ptr: *i32 = &answer;
     50 
     51 pub fn @[.bind(.weak), .visibility(.hidden), .section(".text.hot"), .hot,
     52          .stack_align(16), .target_features(""), .callconv(.target_c)]
     53 decorated(x @[.signext]: i8): i64 @[.zeroext] {
     54   return x as i64;
     55 }
     56 
     57 pub alias decorated_alias = decorated;
     58 
     59 fn add1(x: Word): Word {
     60   return x + 1;
     61 }
     62 
     63 fn tail_add1(x: Word): Word {
     64   return tail add1(x);
     65 }
     66 
     67 fn apply(fp: *Fn1, x: Word): Word {
     68   return fp(x);
     69 }
     70 
     71 fn restrict_first(p: restrict *Word): Word {
     72   return p[0];
     73 }
     74 
     75 fn borrowed(p @[.byref, .readonly, .noalias, .nonnull,
     76                 .dereferenceable(16)]: *Pair): Word {
     77   return p.a + p.b;
     78 }
     79 
     80 fn sum_var(n: Word, ...): Word {
     81   var ap: va_list;
     82   @va_start(ap);
     83   var cp: va_list;
     84   @va_copy(cp, ap);
     85   let first: Word = @va_arg<Word>(cp);
     86   @va_end(cp);
     87 
     88   var i: Word = 0;
     89   var total: Word = 0;
     90   while i < n {
     91     total = total + @va_arg<Word>(ap);
     92     i = i + 1;
     93   }
     94   @va_end(ap);
     95   return total + first;
     96 }
     97 
     98 fn static_next(): Word {
     99   var @[.static] id: Word = 40;
    100   id = id + 1;
    101   return id;
    102 }
    103 
    104 fn aggregate_demo(): Word {
    105   let p: Pair = Pair { a: 10 };
    106   var q: Pair = {};
    107   q.a = p.a;
    108   q.b = pair_global.b;
    109 
    110   let r: Range = Range { 3, 7 };
    111   let xs: [4]Word = [1, 2];
    112   let zeros: [3]Word = [];
    113   return q.a + q.b + r.0 + r.1 + xs[0] + xs[1] + zeros[2] +
    114          @add_overflow<Word>(40, 2).value +
    115          (@add_overflow<Word>(1, 1).overflow as Word) + @offsetof<Pair>(b) +
    116          @offsetof<Range>(1) + @sizeof<Header>() + @alignof<AlignedPair>();
    117 }
    118 
    119 fn enum_demo(mode: Mode): Word {
    120   let selected: Word = switch mode {
    121     .cold {
    122       1
    123     }
    124     .warm {
    125       2
    126     }
    127     .hot {
    128       3
    129     }
    130   };
    131 
    132   switch @[.branch_chain, .jump_table] mode {
    133     .cold {
    134       return selected + 10;
    135     }
    136     .warm, .hot {
    137       return selected + 20;
    138     }
    139   }
    140 
    141   return 0;
    142 }
    143 
    144 fn control_demo(limit: Word): Word {
    145   var i: Word = 0;
    146   var sum: Word = 0;
    147 
    148 outer: while i < limit {
    149     i = i + 1;
    150     if i == 2 {
    151       continue outer;
    152     }
    153     switch i {
    154       5 {
    155         break outer;
    156       }
    157       default {
    158       }
    159     }
    160     sum = sum + i;
    161   }
    162 
    163   let branch: Word = if sum > 5 {
    164     let base = sum;
    165     base + 1
    166   } else {
    167     0
    168   };
    169 
    170   var j: Word = 0;
    171   let found: Word = search: while<Word> j < 10 {
    172     if j == 4 {
    173       break search j;
    174     }
    175     j = j + 1;
    176     continue search;
    177   } else {
    178     -1
    179   };
    180 
    181   return branch + found;
    182 }
    183 
    184 fn memory_demo(n: usize): Word {
    185   let src: *Word = @alloca<Word>(2, 8);
    186   let dst: *Word = @alloca<Word>(2, 8);
    187   let tmp: *Word = @alloca<Word>(2, 8);
    188   src[0] = 20;
    189   src[1] = 22;
    190   @memset(dst, 0, n, 8, .volatile);
    191   @memcpy(dst, src, n, 8);
    192   @memmove(tmp, dst, n, 8);
    193   return restrict_first(tmp);
    194 }
    195 
    196 fn atomic_demo(): Word {
    197   var x: Word = 0;
    198   @atomic_store<Word>(&x, 40, .seq_cst, access(.align(8)));
    199   @atomic_rmw<Word>(.add, &x, 2, .seq_cst, access(.align(8)));
    200   let now: Word = @atomic_load<Word>(&x, .seq_cst, access(.align(8)));
    201   let cas = @atomic_cmpxchg<Word>(&x, now, 43, .seq_cst, .relaxed, .strong,
    202                                   access(.align(8)));
    203   @atomic_fence(.seq_cst);
    204   let legal: bool = @atomic_is_legal<Word>(.seq_cst, access(.align(8)));
    205   let lockfree: bool = @atomic_is_lock_free<Word>(access(.align(8)));
    206   // rv32 i64 atomics are legal via runtime shim but not lock-free.
    207   if legal and (lockfree or !lockfree) and cas.ok {
    208     return x - 1;
    209   }
    210   return 0;
    211 }
    212 
    213 fn intrinsic_demo(): Word {
    214   var x: Word = 7;
    215   let p: *Word = @assume_aligned<*Word>(&x, 8);
    216   @prefetch(p);
    217   let ov = @add_overflow<Word>(40, 2);
    218   let bits: Word = @bitget(@bitset(0, 3, 4, 4), 4, 4);
    219   let conv: Word = @float_to_sint<Word>(
    220       @sint_to_float<f64>(40, .default) +
    221       @uint_to_float<f64>(2, .nearest_even) + 0.75,
    222       .toward_zero);
    223   let ptr_roundtrip: *Word = @int_to_ptr<*Word>(@ptr_to_int<Word>(p));
    224   if ptr_roundtrip == NULL as *Word {
    225     return 0;
    226   }
    227   if ov.value != 42 {
    228     return 0;
    229   }
    230   if bits != 3 {
    231     return 0;
    232   }
    233   if conv != 42 {
    234     return 0;
    235   }
    236   if @popcount(x) != 3 {
    237     return 0;
    238   }
    239   if @ctz(8) != 3 {
    240     return 0;
    241   }
    242   if @clz(1) == 0 {
    243     return 0;
    244   }
    245   if @expect(1, 1) != 1 {
    246     return 0;
    247   }
    248   if @bswap(1 as Word) == 0 {
    249     return 0;
    250   }
    251   if (@fma(2.0, 3.0, 4.0) as Word) != 10 {
    252     return 0;
    253   }
    254   return 42;
    255 }
    256 
    257 fn target_demo(): Word {
    258   let arch_value: Word = switch @target_arch() {
    259     .x64 {
    260       1
    261     }
    262     .arm64 {
    263       2
    264     }
    265     .rv64 {
    266       3
    267     }
    268     default {
    269       4
    270     }
    271   };
    272   let cc_ok: bool = @supports_callconv(.target_c);
    273   let weak_known: bool = @supports_symbol_feature(.weak);
    274   let align_known: bool = @has_backend_feature(.unaligned_memory) or
    275                           @has_backend_feature(.strict_alignment);
    276   if (arch_value != 0) and cc_ok and (weak_known or !weak_known) and
    277      (align_known or !align_known) {
    278     return 1;
    279   }
    280   return 0;
    281 }
    282 
    283 fn label_demo(idx: isize): Word {
    284   label zero;
    285   label one;
    286   label done;
    287 
    288   let @[.static] dispatch: [2]*void = [
    289     @labeladdr(zero),
    290     @labeladdr(one),
    291   ];
    292 
    293   var out: Word = 0;
    294   goto *dispatch[idx] within (zero, one, done);
    295 
    296 zero:
    297   out = 11;
    298   goto *@labeladdr(done) within (done);
    299 one:
    300   out = 42;
    301 done:
    302   return out;
    303 }
    304 
    305 fn __user_main(): Word {
    306   let fp: *Fn1 = &add1;
    307   var local_pair: Pair = Pair { a: 12, b: 30 };
    308   var node: Node = Node { value: 8 };
    309   node.next = &node;
    310 
    311   tentative = numbers[0] + numbers[1];
    312 
    313   let mode: Mode = .warm;
    314   let addrspace_null: *addrspace(1) i32 = NULL as *addrspace(1) i32;
    315   let pointer_check: Word = if addrspace_null == NULL as *addrspace(1) i32 {
    316     1
    317   } else {
    318     0
    319   };
    320 
    321   if tail_add1(1) != 2 {
    322     return 1;
    323   }
    324   if apply(fp, 2) != 3 {
    325     return 2;
    326   }
    327   if borrowed(&local_pair) != 42 {
    328     return 3;
    329   }
    330   if node.next.value != 8 {
    331     return 4;
    332   }
    333   if decorated(5 as i8) != 5 {
    334     return 5;
    335   }
    336   if static_next() != 41 {
    337     return 6;
    338   }
    339   if static_next() != 42 {
    340     return 7;
    341   }
    342   if aggregate_demo() != 107 {
    343     return 8;
    344   }
    345   if enum_demo(mode) != 22 {
    346     return 9;
    347   }
    348   if control_demo(8) != 13 {
    349     return 10;
    350   }
    351   if memory_demo(16) != 20 {
    352     return 11;
    353   }
    354   if atomic_demo() != 42 {
    355     return 12;
    356   }
    357   if intrinsic_demo() != 42 {
    358     return 13;
    359   }
    360   if target_demo() != 1 {
    361     return 14;
    362   }
    363   if label_demo(1) != 42 {
    364     return 15;
    365   }
    366   if sum_var(3, 5 as Word, 6 as Word, 7 as Word) != 23 {
    367     return 16;
    368   }
    369   if (answer_ptr.* as Word) != 42 {
    370     return 17;
    371   }
    372   if pointer_check != 1 {
    373     return 18;
    374   }
    375 
    376   return 42;
    377 }
    378 
    379 fn main(): i32 { return __user_main() as i32; }