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; }