| author | |
| committer | |
| log | fcafc63f3d5ce250e404871571aa3b26aeae6611 |
| tree | 49e3354bb24dd1d8663127598e4f2f63942f2655 |
| parent | 6002514b72cb2a571abc6ac4ac7fbec44d6302b1 |
until now these were stringly typed.
it's kinda obvious when you think about it.25 files changed, 1576 insertions(+), 253 deletions(-)
lib/std/builtin.zig+4-3| ... | @@ -1,6 +1,10 @@ | ... | @@ -1,6 +1,10 @@ |
| 1 | //! Types and values provided by the Zig language. | 1 | //! Types and values provided by the Zig language. |
| 2 | 2 | ||
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const std = @import("std.zig"); | ||
| 5 | const root = @import("root"); | ||
| 6 | |||
| 7 | pub const assembly = @import("builtin/assembly.zig"); | ||
| 4 | 8 | ||
| 5 | /// `explicit_subsystem` is missing when the subsystem is automatically detected, | 9 | /// `explicit_subsystem` is missing when the subsystem is automatically detected, |
| 6 | /// so Zig standard library has the subsystem detection logic here. This should generally be | 10 | /// so Zig standard library has the subsystem detection logic here. This should generally be |
| ... | @@ -1100,6 +1104,3 @@ pub noinline fn returnError() void { | ... | @@ -1100,6 +1104,3 @@ pub noinline fn returnError() void { |
| 1100 | st.instruction_addresses[st.index] = @returnAddress(); | 1104 | st.instruction_addresses[st.index] = @returnAddress(); |
| 1101 | st.index += 1; | 1105 | st.index += 1; |
| 1102 | } | 1106 | } |
| 1103 | |||
| 1104 | const std = @import("std.zig"); | ||
| 1105 | const root = @import("root"); |
lib/std/builtin/assembly.zig created+1026| ... | @@ -0,0 +1,1026 @@ | ||
| 1 | pub const Clobbers = switch (@import("builtin").cpu.arch) { | ||
| 2 | .x86, .x86_64 => packed struct { | ||
| 3 | /// Whether the inline assembly code may perform stores to memory | ||
| 4 | /// addresses other than those derived from input pointer provenance. | ||
| 5 | memory: bool = false, | ||
| 6 | |||
| 7 | cc: bool = false, | ||
| 8 | dirflag: bool = false, | ||
| 9 | eflags: bool = false, | ||
| 10 | flags: bool = false, | ||
| 11 | fpcr: bool = false, | ||
| 12 | fpsr: bool = false, | ||
| 13 | mxcsr: bool = false, | ||
| 14 | rflags: bool = false, | ||
| 15 | |||
| 16 | rax: bool = false, | ||
| 17 | rcx: bool = false, | ||
| 18 | rdx: bool = false, | ||
| 19 | rbx: bool = false, | ||
| 20 | rsp: bool = false, | ||
| 21 | rbp: bool = false, | ||
| 22 | rsi: bool = false, | ||
| 23 | rdi: bool = false, | ||
| 24 | r8: bool = false, | ||
| 25 | r9: bool = false, | ||
| 26 | r10: bool = false, | ||
| 27 | r11: bool = false, | ||
| 28 | r12: bool = false, | ||
| 29 | r13: bool = false, | ||
| 30 | r14: bool = false, | ||
| 31 | r15: bool = false, | ||
| 32 | eax: bool = false, | ||
| 33 | ecx: bool = false, | ||
| 34 | edx: bool = false, | ||
| 35 | ebx: bool = false, | ||
| 36 | esp: bool = false, | ||
| 37 | ebp: bool = false, | ||
| 38 | esi: bool = false, | ||
| 39 | edi: bool = false, | ||
| 40 | r8d: bool = false, | ||
| 41 | r9d: bool = false, | ||
| 42 | r10d: bool = false, | ||
| 43 | r11d: bool = false, | ||
| 44 | r12d: bool = false, | ||
| 45 | r13d: bool = false, | ||
| 46 | r14d: bool = false, | ||
| 47 | r15d: bool = false, | ||
| 48 | ax: bool = false, | ||
| 49 | cx: bool = false, | ||
| 50 | dx: bool = false, | ||
| 51 | bx: bool = false, | ||
| 52 | sp: bool = false, | ||
| 53 | bp: bool = false, | ||
| 54 | si: bool = false, | ||
| 55 | di: bool = false, | ||
| 56 | r8w: bool = false, | ||
| 57 | r9w: bool = false, | ||
| 58 | r10w: bool = false, | ||
| 59 | r11w: bool = false, | ||
| 60 | r12w: bool = false, | ||
| 61 | r13w: bool = false, | ||
| 62 | r14w: bool = false, | ||
| 63 | r15w: bool = false, | ||
| 64 | al: bool = false, | ||
| 65 | cl: bool = false, | ||
| 66 | dl: bool = false, | ||
| 67 | bl: bool = false, | ||
| 68 | spl: bool = false, | ||
| 69 | bpl: bool = false, | ||
| 70 | sil: bool = false, | ||
| 71 | dil: bool = false, | ||
| 72 | r8b: bool = false, | ||
| 73 | r9b: bool = false, | ||
| 74 | r10b: bool = false, | ||
| 75 | r11b: bool = false, | ||
| 76 | r12b: bool = false, | ||
| 77 | r13b: bool = false, | ||
| 78 | r14b: bool = false, | ||
| 79 | r15b: bool = false, | ||
| 80 | ah: bool = false, | ||
| 81 | ch: bool = false, | ||
| 82 | dh: bool = false, | ||
| 83 | bh: bool = false, | ||
| 84 | zmm0: bool = false, | ||
| 85 | zmm1: bool = false, | ||
| 86 | zmm2: bool = false, | ||
| 87 | zmm3: bool = false, | ||
| 88 | zmm4: bool = false, | ||
| 89 | zmm5: bool = false, | ||
| 90 | zmm6: bool = false, | ||
| 91 | zmm7: bool = false, | ||
| 92 | zmm8: bool = false, | ||
| 93 | zmm9: bool = false, | ||
| 94 | zmm10: bool = false, | ||
| 95 | zmm11: bool = false, | ||
| 96 | zmm12: bool = false, | ||
| 97 | zmm13: bool = false, | ||
| 98 | zmm14: bool = false, | ||
| 99 | zmm15: bool = false, | ||
| 100 | zmm16: bool = false, | ||
| 101 | zmm17: bool = false, | ||
| 102 | zmm18: bool = false, | ||
| 103 | zmm19: bool = false, | ||
| 104 | zmm20: bool = false, | ||
| 105 | zmm21: bool = false, | ||
| 106 | zmm22: bool = false, | ||
| 107 | zmm23: bool = false, | ||
| 108 | zmm24: bool = false, | ||
| 109 | zmm25: bool = false, | ||
| 110 | zmm26: bool = false, | ||
| 111 | zmm27: bool = false, | ||
| 112 | zmm28: bool = false, | ||
| 113 | zmm29: bool = false, | ||
| 114 | zmm30: bool = false, | ||
| 115 | zmm31: bool = false, | ||
| 116 | ymm0: bool = false, | ||
| 117 | ymm1: bool = false, | ||
| 118 | ymm2: bool = false, | ||
| 119 | ymm3: bool = false, | ||
| 120 | ymm4: bool = false, | ||
| 121 | ymm5: bool = false, | ||
| 122 | ymm6: bool = false, | ||
| 123 | ymm7: bool = false, | ||
| 124 | ymm8: bool = false, | ||
| 125 | ymm9: bool = false, | ||
| 126 | ymm10: bool = false, | ||
| 127 | ymm11: bool = false, | ||
| 128 | ymm12: bool = false, | ||
| 129 | ymm13: bool = false, | ||
| 130 | ymm14: bool = false, | ||
| 131 | ymm15: bool = false, | ||
| 132 | ymm16: bool = false, | ||
| 133 | ymm17: bool = false, | ||
| 134 | ymm18: bool = false, | ||
| 135 | ymm19: bool = false, | ||
| 136 | ymm20: bool = false, | ||
| 137 | ymm21: bool = false, | ||
| 138 | ymm22: bool = false, | ||
| 139 | ymm23: bool = false, | ||
| 140 | ymm24: bool = false, | ||
| 141 | ymm25: bool = false, | ||
| 142 | ymm26: bool = false, | ||
| 143 | ymm27: bool = false, | ||
| 144 | ymm28: bool = false, | ||
| 145 | ymm29: bool = false, | ||
| 146 | ymm30: bool = false, | ||
| 147 | ymm31: bool = false, | ||
| 148 | xmm0: bool = false, | ||
| 149 | xmm1: bool = false, | ||
| 150 | xmm2: bool = false, | ||
| 151 | xmm3: bool = false, | ||
| 152 | xmm4: bool = false, | ||
| 153 | xmm5: bool = false, | ||
| 154 | xmm6: bool = false, | ||
| 155 | xmm7: bool = false, | ||
| 156 | xmm8: bool = false, | ||
| 157 | xmm9: bool = false, | ||
| 158 | xmm10: bool = false, | ||
| 159 | xmm11: bool = false, | ||
| 160 | xmm12: bool = false, | ||
| 161 | xmm13: bool = false, | ||
| 162 | xmm14: bool = false, | ||
| 163 | xmm15: bool = false, | ||
| 164 | xmm16: bool = false, | ||
| 165 | xmm17: bool = false, | ||
| 166 | xmm18: bool = false, | ||
| 167 | xmm19: bool = false, | ||
| 168 | xmm20: bool = false, | ||
| 169 | xmm21: bool = false, | ||
| 170 | xmm22: bool = false, | ||
| 171 | xmm23: bool = false, | ||
| 172 | xmm24: bool = false, | ||
| 173 | xmm25: bool = false, | ||
| 174 | xmm26: bool = false, | ||
| 175 | xmm27: bool = false, | ||
| 176 | xmm28: bool = false, | ||
| 177 | xmm29: bool = false, | ||
| 178 | xmm30: bool = false, | ||
| 179 | xmm31: bool = false, | ||
| 180 | mm0: bool = false, | ||
| 181 | mm1: bool = false, | ||
| 182 | mm2: bool = false, | ||
| 183 | mm3: bool = false, | ||
| 184 | mm4: bool = false, | ||
| 185 | mm5: bool = false, | ||
| 186 | mm6: bool = false, | ||
| 187 | mm7: bool = false, | ||
| 188 | st0: bool = false, | ||
| 189 | st1: bool = false, | ||
| 190 | st2: bool = false, | ||
| 191 | st3: bool = false, | ||
| 192 | st4: bool = false, | ||
| 193 | st5: bool = false, | ||
| 194 | st6: bool = false, | ||
| 195 | st7: bool = false, | ||
| 196 | es: bool = false, | ||
| 197 | cs: bool = false, | ||
| 198 | ss: bool = false, | ||
| 199 | ds: bool = false, | ||
| 200 | fs: bool = false, | ||
| 201 | gs: bool = false, | ||
| 202 | rip: bool = false, | ||
| 203 | eip: bool = false, | ||
| 204 | ip: bool = false, | ||
| 205 | cr0: bool = false, | ||
| 206 | cr1: bool = false, | ||
| 207 | cr2: bool = false, | ||
| 208 | cr3: bool = false, | ||
| 209 | cr4: bool = false, | ||
| 210 | cr5: bool = false, | ||
| 211 | cr6: bool = false, | ||
| 212 | cr7: bool = false, | ||
| 213 | cr8: bool = false, | ||
| 214 | cr9: bool = false, | ||
| 215 | cr10: bool = false, | ||
| 216 | cr11: bool = false, | ||
| 217 | cr12: bool = false, | ||
| 218 | cr13: bool = false, | ||
| 219 | cr14: bool = false, | ||
| 220 | cr15: bool = false, | ||
| 221 | dr0: bool = false, | ||
| 222 | dr1: bool = false, | ||
| 223 | dr2: bool = false, | ||
| 224 | dr3: bool = false, | ||
| 225 | dr4: bool = false, | ||
| 226 | dr5: bool = false, | ||
| 227 | dr6: bool = false, | ||
| 228 | dr7: bool = false, | ||
| 229 | dr8: bool = false, | ||
| 230 | dr9: bool = false, | ||
| 231 | dr10: bool = false, | ||
| 232 | dr11: bool = false, | ||
| 233 | dr12: bool = false, | ||
| 234 | dr13: bool = false, | ||
| 235 | dr14: bool = false, | ||
| 236 | dr15: bool = false, | ||
| 237 | }, | ||
| 238 | .aarch64, .aarch64_be => packed struct { | ||
| 239 | /// Whether the inline assembly code may perform stores to memory | ||
| 240 | /// addresses other than those derived from input pointer provenance. | ||
| 241 | memory: bool = false, | ||
| 242 | |||
| 243 | nzcv: bool = false, | ||
| 244 | |||
| 245 | x0: bool = false, | ||
| 246 | x1: bool = false, | ||
| 247 | x2: bool = false, | ||
| 248 | x3: bool = false, | ||
| 249 | x4: bool = false, | ||
| 250 | x5: bool = false, | ||
| 251 | x6: bool = false, | ||
| 252 | x7: bool = false, | ||
| 253 | x8: bool = false, | ||
| 254 | x9: bool = false, | ||
| 255 | x10: bool = false, | ||
| 256 | x11: bool = false, | ||
| 257 | x12: bool = false, | ||
| 258 | x13: bool = false, | ||
| 259 | x14: bool = false, | ||
| 260 | x15: bool = false, | ||
| 261 | x16: bool = false, | ||
| 262 | x17: bool = false, | ||
| 263 | x18: bool = false, | ||
| 264 | x19: bool = false, | ||
| 265 | x20: bool = false, | ||
| 266 | x21: bool = false, | ||
| 267 | x22: bool = false, | ||
| 268 | x23: bool = false, | ||
| 269 | x24: bool = false, | ||
| 270 | x25: bool = false, | ||
| 271 | x26: bool = false, | ||
| 272 | x27: bool = false, | ||
| 273 | x28: bool = false, | ||
| 274 | x29: bool = false, | ||
| 275 | x30: bool = false, | ||
| 276 | |||
| 277 | w0: bool = false, | ||
| 278 | w1: bool = false, | ||
| 279 | w2: bool = false, | ||
| 280 | w3: bool = false, | ||
| 281 | w4: bool = false, | ||
| 282 | w5: bool = false, | ||
| 283 | w6: bool = false, | ||
| 284 | w7: bool = false, | ||
| 285 | w8: bool = false, | ||
| 286 | w9: bool = false, | ||
| 287 | w10: bool = false, | ||
| 288 | w11: bool = false, | ||
| 289 | w12: bool = false, | ||
| 290 | w13: bool = false, | ||
| 291 | w14: bool = false, | ||
| 292 | w15: bool = false, | ||
| 293 | w16: bool = false, | ||
| 294 | w17: bool = false, | ||
| 295 | w18: bool = false, | ||
| 296 | w19: bool = false, | ||
| 297 | w20: bool = false, | ||
| 298 | w21: bool = false, | ||
| 299 | w22: bool = false, | ||
| 300 | w23: bool = false, | ||
| 301 | w24: bool = false, | ||
| 302 | w25: bool = false, | ||
| 303 | w26: bool = false, | ||
| 304 | w27: bool = false, | ||
| 305 | w28: bool = false, | ||
| 306 | w29: bool = false, | ||
| 307 | w30: bool = false, | ||
| 308 | |||
| 309 | lr: bool = false, | ||
| 310 | sp: bool = false, | ||
| 311 | wsp: bool = false, | ||
| 312 | fpcr: bool = false, | ||
| 313 | fpmr: bool = false, | ||
| 314 | fpsr: bool = false, | ||
| 315 | ffr: bool = false, | ||
| 316 | |||
| 317 | p0: bool = false, | ||
| 318 | p1: bool = false, | ||
| 319 | p2: bool = false, | ||
| 320 | p3: bool = false, | ||
| 321 | p4: bool = false, | ||
| 322 | p5: bool = false, | ||
| 323 | p6: bool = false, | ||
| 324 | p7: bool = false, | ||
| 325 | p8: bool = false, | ||
| 326 | p9: bool = false, | ||
| 327 | p10: bool = false, | ||
| 328 | p11: bool = false, | ||
| 329 | p12: bool = false, | ||
| 330 | p13: bool = false, | ||
| 331 | p14: bool = false, | ||
| 332 | p15: bool = false, | ||
| 333 | |||
| 334 | z0: bool = false, | ||
| 335 | z1: bool = false, | ||
| 336 | z2: bool = false, | ||
| 337 | z3: bool = false, | ||
| 338 | z4: bool = false, | ||
| 339 | z5: bool = false, | ||
| 340 | z6: bool = false, | ||
| 341 | z7: bool = false, | ||
| 342 | z8: bool = false, | ||
| 343 | z9: bool = false, | ||
| 344 | z10: bool = false, | ||
| 345 | z11: bool = false, | ||
| 346 | z12: bool = false, | ||
| 347 | z13: bool = false, | ||
| 348 | z14: bool = false, | ||
| 349 | z15: bool = false, | ||
| 350 | z16: bool = false, | ||
| 351 | z17: bool = false, | ||
| 352 | z18: bool = false, | ||
| 353 | z19: bool = false, | ||
| 354 | z20: bool = false, | ||
| 355 | z21: bool = false, | ||
| 356 | z22: bool = false, | ||
| 357 | z23: bool = false, | ||
| 358 | z24: bool = false, | ||
| 359 | z25: bool = false, | ||
| 360 | z26: bool = false, | ||
| 361 | z27: bool = false, | ||
| 362 | z28: bool = false, | ||
| 363 | z29: bool = false, | ||
| 364 | z30: bool = false, | ||
| 365 | z31: bool = false, | ||
| 366 | |||
| 367 | v0: bool = false, | ||
| 368 | v1: bool = false, | ||
| 369 | v2: bool = false, | ||
| 370 | v3: bool = false, | ||
| 371 | v4: bool = false, | ||
| 372 | v5: bool = false, | ||
| 373 | v6: bool = false, | ||
| 374 | v7: bool = false, | ||
| 375 | v8: bool = false, | ||
| 376 | v9: bool = false, | ||
| 377 | v10: bool = false, | ||
| 378 | v11: bool = false, | ||
| 379 | v12: bool = false, | ||
| 380 | v13: bool = false, | ||
| 381 | v14: bool = false, | ||
| 382 | v15: bool = false, | ||
| 383 | v16: bool = false, | ||
| 384 | v17: bool = false, | ||
| 385 | v18: bool = false, | ||
| 386 | v19: bool = false, | ||
| 387 | v20: bool = false, | ||
| 388 | v21: bool = false, | ||
| 389 | v22: bool = false, | ||
| 390 | v23: bool = false, | ||
| 391 | v24: bool = false, | ||
| 392 | v25: bool = false, | ||
| 393 | v26: bool = false, | ||
| 394 | v27: bool = false, | ||
| 395 | v28: bool = false, | ||
| 396 | v29: bool = false, | ||
| 397 | v30: bool = false, | ||
| 398 | v31: bool = false, | ||
| 399 | |||
| 400 | d0: bool = false, | ||
| 401 | d1: bool = false, | ||
| 402 | d2: bool = false, | ||
| 403 | d3: bool = false, | ||
| 404 | d4: bool = false, | ||
| 405 | d5: bool = false, | ||
| 406 | d6: bool = false, | ||
| 407 | d7: bool = false, | ||
| 408 | d8: bool = false, | ||
| 409 | d9: bool = false, | ||
| 410 | d10: bool = false, | ||
| 411 | d11: bool = false, | ||
| 412 | d12: bool = false, | ||
| 413 | d13: bool = false, | ||
| 414 | d14: bool = false, | ||
| 415 | d15: bool = false, | ||
| 416 | d16: bool = false, | ||
| 417 | d17: bool = false, | ||
| 418 | d18: bool = false, | ||
| 419 | d19: bool = false, | ||
| 420 | d20: bool = false, | ||
| 421 | d21: bool = false, | ||
| 422 | d22: bool = false, | ||
| 423 | d23: bool = false, | ||
| 424 | d24: bool = false, | ||
| 425 | d25: bool = false, | ||
| 426 | d26: bool = false, | ||
| 427 | d27: bool = false, | ||
| 428 | d28: bool = false, | ||
| 429 | d29: bool = false, | ||
| 430 | d30: bool = false, | ||
| 431 | d31: bool = false, | ||
| 432 | |||
| 433 | s0: bool = false, | ||
| 434 | s1: bool = false, | ||
| 435 | s2: bool = false, | ||
| 436 | s3: bool = false, | ||
| 437 | s4: bool = false, | ||
| 438 | s5: bool = false, | ||
| 439 | s6: bool = false, | ||
| 440 | s7: bool = false, | ||
| 441 | s8: bool = false, | ||
| 442 | s9: bool = false, | ||
| 443 | s10: bool = false, | ||
| 444 | s11: bool = false, | ||
| 445 | s12: bool = false, | ||
| 446 | s13: bool = false, | ||
| 447 | s14: bool = false, | ||
| 448 | s15: bool = false, | ||
| 449 | s16: bool = false, | ||
| 450 | s17: bool = false, | ||
| 451 | s18: bool = false, | ||
| 452 | s19: bool = false, | ||
| 453 | s20: bool = false, | ||
| 454 | s21: bool = false, | ||
| 455 | s22: bool = false, | ||
| 456 | s23: bool = false, | ||
| 457 | s24: bool = false, | ||
| 458 | s25: bool = false, | ||
| 459 | s26: bool = false, | ||
| 460 | s27: bool = false, | ||
| 461 | s28: bool = false, | ||
| 462 | s29: bool = false, | ||
| 463 | s30: bool = false, | ||
| 464 | s31: bool = false, | ||
| 465 | |||
| 466 | h0: bool = false, | ||
| 467 | h1: bool = false, | ||
| 468 | h2: bool = false, | ||
| 469 | h3: bool = false, | ||
| 470 | h4: bool = false, | ||
| 471 | h5: bool = false, | ||
| 472 | h6: bool = false, | ||
| 473 | h7: bool = false, | ||
| 474 | h8: bool = false, | ||
| 475 | h9: bool = false, | ||
| 476 | h10: bool = false, | ||
| 477 | h11: bool = false, | ||
| 478 | h12: bool = false, | ||
| 479 | h13: bool = false, | ||
| 480 | h14: bool = false, | ||
| 481 | h15: bool = false, | ||
| 482 | h16: bool = false, | ||
| 483 | h17: bool = false, | ||
| 484 | h18: bool = false, | ||
| 485 | h19: bool = false, | ||
| 486 | h20: bool = false, | ||
| 487 | h21: bool = false, | ||
| 488 | h22: bool = false, | ||
| 489 | h23: bool = false, | ||
| 490 | h24: bool = false, | ||
| 491 | h25: bool = false, | ||
| 492 | h26: bool = false, | ||
| 493 | h27: bool = false, | ||
| 494 | h28: bool = false, | ||
| 495 | h29: bool = false, | ||
| 496 | h30: bool = false, | ||
| 497 | h31: bool = false, | ||
| 498 | |||
| 499 | b0: bool = false, | ||
| 500 | b1: bool = false, | ||
| 501 | b2: bool = false, | ||
| 502 | b3: bool = false, | ||
| 503 | b4: bool = false, | ||
| 504 | b5: bool = false, | ||
| 505 | b6: bool = false, | ||
| 506 | b7: bool = false, | ||
| 507 | b8: bool = false, | ||
| 508 | b9: bool = false, | ||
| 509 | b10: bool = false, | ||
| 510 | b11: bool = false, | ||
| 511 | b12: bool = false, | ||
| 512 | b13: bool = false, | ||
| 513 | b14: bool = false, | ||
| 514 | b15: bool = false, | ||
| 515 | b16: bool = false, | ||
| 516 | b17: bool = false, | ||
| 517 | b18: bool = false, | ||
| 518 | b19: bool = false, | ||
| 519 | b20: bool = false, | ||
| 520 | b21: bool = false, | ||
| 521 | b22: bool = false, | ||
| 522 | b23: bool = false, | ||
| 523 | b24: bool = false, | ||
| 524 | b25: bool = false, | ||
| 525 | b26: bool = false, | ||
| 526 | b27: bool = false, | ||
| 527 | b28: bool = false, | ||
| 528 | b29: bool = false, | ||
| 529 | b30: bool = false, | ||
| 530 | b31: bool = false, | ||
| 531 | |||
| 532 | za0: bool = false, | ||
| 533 | za1: bool = false, | ||
| 534 | za2: bool = false, | ||
| 535 | za3: bool = false, | ||
| 536 | za4: bool = false, | ||
| 537 | za5: bool = false, | ||
| 538 | za6: bool = false, | ||
| 539 | za7: bool = false, | ||
| 540 | za8: bool = false, | ||
| 541 | za9: bool = false, | ||
| 542 | za10: bool = false, | ||
| 543 | za11: bool = false, | ||
| 544 | za12: bool = false, | ||
| 545 | za13: bool = false, | ||
| 546 | za14: bool = false, | ||
| 547 | za15: bool = false, | ||
| 548 | |||
| 549 | zt0: bool = false, | ||
| 550 | }, | ||
| 551 | .arm, .armeb => packed struct { | ||
| 552 | /// Whether the inline assembly code may perform stores to memory | ||
| 553 | /// addresses other than those derived from input pointer provenance. | ||
| 554 | memory: bool = false, | ||
| 555 | |||
| 556 | apsr: bool = false, | ||
| 557 | cpsr: bool = false, | ||
| 558 | spsr: bool = false, | ||
| 559 | r0: bool = false, | ||
| 560 | r1: bool = false, | ||
| 561 | r2: bool = false, | ||
| 562 | r3: bool = false, | ||
| 563 | r4: bool = false, | ||
| 564 | r5: bool = false, | ||
| 565 | r6: bool = false, | ||
| 566 | r7: bool = false, | ||
| 567 | r8: bool = false, | ||
| 568 | r9: bool = false, | ||
| 569 | r10: bool = false, | ||
| 570 | r11: bool = false, | ||
| 571 | r12: bool = false, | ||
| 572 | r13: bool = false, | ||
| 573 | r14: bool = false, | ||
| 574 | r15: bool = false, | ||
| 575 | |||
| 576 | fpscr: bool = false, | ||
| 577 | vpr: bool = false, | ||
| 578 | |||
| 579 | d0: bool = false, | ||
| 580 | d1: bool = false, | ||
| 581 | d2: bool = false, | ||
| 582 | d3: bool = false, | ||
| 583 | d4: bool = false, | ||
| 584 | d5: bool = false, | ||
| 585 | d6: bool = false, | ||
| 586 | d7: bool = false, | ||
| 587 | d8: bool = false, | ||
| 588 | d9: bool = false, | ||
| 589 | d10: bool = false, | ||
| 590 | d11: bool = false, | ||
| 591 | d12: bool = false, | ||
| 592 | d13: bool = false, | ||
| 593 | d14: bool = false, | ||
| 594 | d15: bool = false, | ||
| 595 | d16: bool = false, | ||
| 596 | d17: bool = false, | ||
| 597 | d18: bool = false, | ||
| 598 | d19: bool = false, | ||
| 599 | d20: bool = false, | ||
| 600 | d21: bool = false, | ||
| 601 | d22: bool = false, | ||
| 602 | d23: bool = false, | ||
| 603 | d24: bool = false, | ||
| 604 | d25: bool = false, | ||
| 605 | d26: bool = false, | ||
| 606 | d27: bool = false, | ||
| 607 | d28: bool = false, | ||
| 608 | d29: bool = false, | ||
| 609 | d30: bool = false, | ||
| 610 | d31: bool = false, | ||
| 611 | |||
| 612 | s0: bool = false, | ||
| 613 | s1: bool = false, | ||
| 614 | s2: bool = false, | ||
| 615 | s3: bool = false, | ||
| 616 | s4: bool = false, | ||
| 617 | s5: bool = false, | ||
| 618 | s6: bool = false, | ||
| 619 | s7: bool = false, | ||
| 620 | s8: bool = false, | ||
| 621 | s9: bool = false, | ||
| 622 | s10: bool = false, | ||
| 623 | s11: bool = false, | ||
| 624 | s12: bool = false, | ||
| 625 | s13: bool = false, | ||
| 626 | s14: bool = false, | ||
| 627 | s15: bool = false, | ||
| 628 | s16: bool = false, | ||
| 629 | s17: bool = false, | ||
| 630 | s18: bool = false, | ||
| 631 | s19: bool = false, | ||
| 632 | s20: bool = false, | ||
| 633 | s21: bool = false, | ||
| 634 | s22: bool = false, | ||
| 635 | s23: bool = false, | ||
| 636 | s24: bool = false, | ||
| 637 | s25: bool = false, | ||
| 638 | s26: bool = false, | ||
| 639 | s27: bool = false, | ||
| 640 | s28: bool = false, | ||
| 641 | s29: bool = false, | ||
| 642 | s30: bool = false, | ||
| 643 | s31: bool = false, | ||
| 644 | |||
| 645 | q0: bool = false, | ||
| 646 | q1: bool = false, | ||
| 647 | q2: bool = false, | ||
| 648 | q3: bool = false, | ||
| 649 | q4: bool = false, | ||
| 650 | q5: bool = false, | ||
| 651 | q6: bool = false, | ||
| 652 | q7: bool = false, | ||
| 653 | q8: bool = false, | ||
| 654 | q9: bool = false, | ||
| 655 | q10: bool = false, | ||
| 656 | q11: bool = false, | ||
| 657 | q12: bool = false, | ||
| 658 | q13: bool = false, | ||
| 659 | q14: bool = false, | ||
| 660 | q15: bool = false, | ||
| 661 | }, | ||
| 662 | .riscv32, .riscv64 => packed struct { | ||
| 663 | /// Whether the inline assembly code may perform stores to memory | ||
| 664 | /// addresses other than those derived from input pointer provenance. | ||
| 665 | memory: bool = false, | ||
| 666 | |||
| 667 | ssp: bool = false, | ||
| 668 | |||
| 669 | x1: bool = false, | ||
| 670 | x2: bool = false, | ||
| 671 | x3: bool = false, | ||
| 672 | x4: bool = false, | ||
| 673 | x5: bool = false, | ||
| 674 | x6: bool = false, | ||
| 675 | x7: bool = false, | ||
| 676 | x8: bool = false, | ||
| 677 | x9: bool = false, | ||
| 678 | x10: bool = false, | ||
| 679 | x11: bool = false, | ||
| 680 | x12: bool = false, | ||
| 681 | x13: bool = false, | ||
| 682 | x14: bool = false, | ||
| 683 | x15: bool = false, | ||
| 684 | x16: bool = false, | ||
| 685 | x17: bool = false, | ||
| 686 | x18: bool = false, | ||
| 687 | x19: bool = false, | ||
| 688 | x20: bool = false, | ||
| 689 | x21: bool = false, | ||
| 690 | x22: bool = false, | ||
| 691 | x23: bool = false, | ||
| 692 | x24: bool = false, | ||
| 693 | x25: bool = false, | ||
| 694 | x26: bool = false, | ||
| 695 | x27: bool = false, | ||
| 696 | x28: bool = false, | ||
| 697 | x29: bool = false, | ||
| 698 | x30: bool = false, | ||
| 699 | x31: bool = false, | ||
| 700 | |||
| 701 | fflags: bool = false, | ||
| 702 | frm: bool = false, | ||
| 703 | |||
| 704 | f0: bool = false, | ||
| 705 | f1: bool = false, | ||
| 706 | f2: bool = false, | ||
| 707 | f3: bool = false, | ||
| 708 | f4: bool = false, | ||
| 709 | f5: bool = false, | ||
| 710 | f6: bool = false, | ||
| 711 | f7: bool = false, | ||
| 712 | f8: bool = false, | ||
| 713 | f9: bool = false, | ||
| 714 | f10: bool = false, | ||
| 715 | f11: bool = false, | ||
| 716 | f12: bool = false, | ||
| 717 | f13: bool = false, | ||
| 718 | f14: bool = false, | ||
| 719 | f15: bool = false, | ||
| 720 | f16: bool = false, | ||
| 721 | f17: bool = false, | ||
| 722 | f18: bool = false, | ||
| 723 | f19: bool = false, | ||
| 724 | f20: bool = false, | ||
| 725 | f21: bool = false, | ||
| 726 | f22: bool = false, | ||
| 727 | f23: bool = false, | ||
| 728 | f24: bool = false, | ||
| 729 | f25: bool = false, | ||
| 730 | f26: bool = false, | ||
| 731 | f27: bool = false, | ||
| 732 | f28: bool = false, | ||
| 733 | f29: bool = false, | ||
| 734 | f30: bool = false, | ||
| 735 | f31: bool = false, | ||
| 736 | |||
| 737 | vtype: bool = false, | ||
| 738 | vl: bool = false, | ||
| 739 | vxsat: bool = false, | ||
| 740 | vxrm: bool = false, | ||
| 741 | vcsr: bool = false, | ||
| 742 | |||
| 743 | v0: bool = false, | ||
| 744 | v1: bool = false, | ||
| 745 | v2: bool = false, | ||
| 746 | v3: bool = false, | ||
| 747 | v4: bool = false, | ||
| 748 | v5: bool = false, | ||
| 749 | v6: bool = false, | ||
| 750 | v7: bool = false, | ||
| 751 | v8: bool = false, | ||
| 752 | v9: bool = false, | ||
| 753 | v10: bool = false, | ||
| 754 | v11: bool = false, | ||
| 755 | v12: bool = false, | ||
| 756 | v13: bool = false, | ||
| 757 | v14: bool = false, | ||
| 758 | v15: bool = false, | ||
| 759 | v16: bool = false, | ||
| 760 | v17: bool = false, | ||
| 761 | v18: bool = false, | ||
| 762 | v19: bool = false, | ||
| 763 | v20: bool = false, | ||
| 764 | v21: bool = false, | ||
| 765 | v22: bool = false, | ||
| 766 | v23: bool = false, | ||
| 767 | v24: bool = false, | ||
| 768 | v25: bool = false, | ||
| 769 | v26: bool = false, | ||
| 770 | v27: bool = false, | ||
| 771 | v28: bool = false, | ||
| 772 | v29: bool = false, | ||
| 773 | v30: bool = false, | ||
| 774 | v31: bool = false, | ||
| 775 | }, | ||
| 776 | .xcore => packed struct { | ||
| 777 | /// Whether the inline assembly code may perform stores to memory | ||
| 778 | /// addresses other than those derived from input pointer provenance. | ||
| 779 | memory: bool = false, | ||
| 780 | |||
| 781 | r0: bool = false, | ||
| 782 | r1: bool = false, | ||
| 783 | r2: bool = false, | ||
| 784 | r3: bool = false, | ||
| 785 | r4: bool = false, | ||
| 786 | r5: bool = false, | ||
| 787 | r6: bool = false, | ||
| 788 | r7: bool = false, | ||
| 789 | r8: bool = false, | ||
| 790 | r9: bool = false, | ||
| 791 | r10: bool = false, | ||
| 792 | r11: bool = false, | ||
| 793 | |||
| 794 | cp: bool = false, | ||
| 795 | dp: bool = false, | ||
| 796 | sp: bool = false, | ||
| 797 | lr: bool = false, | ||
| 798 | sr: bool = false, | ||
| 799 | }, | ||
| 800 | .xtensa => packed struct { | ||
| 801 | /// Whether the inline assembly code may perform stores to memory | ||
| 802 | /// addresses other than those derived from input pointer provenance. | ||
| 803 | memory: bool = false, | ||
| 804 | |||
| 805 | sar: bool = false, | ||
| 806 | lbeg: bool = false, | ||
| 807 | lend: bool = false, | ||
| 808 | lcount: bool = false, | ||
| 809 | atomctl: bool = false, | ||
| 810 | scompare1: bool = false, | ||
| 811 | threadptr: bool = false, | ||
| 812 | litbase: bool = false, | ||
| 813 | windowbase: bool = false, | ||
| 814 | windowstart: bool = false, | ||
| 815 | ps: bool = false, | ||
| 816 | |||
| 817 | a0: bool = false, | ||
| 818 | a1: bool = false, | ||
| 819 | a2: bool = false, | ||
| 820 | a3: bool = false, | ||
| 821 | a4: bool = false, | ||
| 822 | a5: bool = false, | ||
| 823 | a6: bool = false, | ||
| 824 | a7: bool = false, | ||
| 825 | a8: bool = false, | ||
| 826 | a9: bool = false, | ||
| 827 | a10: bool = false, | ||
| 828 | a11: bool = false, | ||
| 829 | a12: bool = false, | ||
| 830 | a13: bool = false, | ||
| 831 | a14: bool = false, | ||
| 832 | a15: bool = false, | ||
| 833 | |||
| 834 | b0: bool = false, | ||
| 835 | b1: bool = false, | ||
| 836 | b2: bool = false, | ||
| 837 | b3: bool = false, | ||
| 838 | b4: bool = false, | ||
| 839 | b5: bool = false, | ||
| 840 | b6: bool = false, | ||
| 841 | b7: bool = false, | ||
| 842 | b8: bool = false, | ||
| 843 | b9: bool = false, | ||
| 844 | b10: bool = false, | ||
| 845 | b11: bool = false, | ||
| 846 | b12: bool = false, | ||
| 847 | b13: bool = false, | ||
| 848 | b14: bool = false, | ||
| 849 | b15: bool = false, | ||
| 850 | |||
| 851 | br: bool = false, | ||
| 852 | acchi: bool = false, | ||
| 853 | acclo: bool = false, | ||
| 854 | m0: bool = false, | ||
| 855 | m1: bool = false, | ||
| 856 | m2: bool = false, | ||
| 857 | m3: bool = false, | ||
| 858 | fcr: bool = false, | ||
| 859 | fsr: bool = false, | ||
| 860 | |||
| 861 | f0: bool = false, | ||
| 862 | f1: bool = false, | ||
| 863 | f2: bool = false, | ||
| 864 | f3: bool = false, | ||
| 865 | f4: bool = false, | ||
| 866 | f5: bool = false, | ||
| 867 | f6: bool = false, | ||
| 868 | f7: bool = false, | ||
| 869 | f8: bool = false, | ||
| 870 | f9: bool = false, | ||
| 871 | f10: bool = false, | ||
| 872 | f11: bool = false, | ||
| 873 | f12: bool = false, | ||
| 874 | f13: bool = false, | ||
| 875 | f14: bool = false, | ||
| 876 | f15: bool = false, | ||
| 877 | }, | ||
| 878 | .lanai => packed struct { | ||
| 879 | /// Whether the inline assembly code may perform stores to memory | ||
| 880 | /// addresses other than those derived from input pointer provenance. | ||
| 881 | memory: bool = false, | ||
| 882 | /// Condition flags which aren't accessible outside of conditional execution. | ||
| 883 | sw: bool = false, | ||
| 884 | |||
| 885 | r3: bool = false, | ||
| 886 | r4: bool = false, | ||
| 887 | r5: bool = false, | ||
| 888 | r6: bool = false, | ||
| 889 | r7: bool = false, | ||
| 890 | r8: bool = false, | ||
| 891 | r9: bool = false, | ||
| 892 | r10: bool = false, | ||
| 893 | r11: bool = false, | ||
| 894 | r12: bool = false, | ||
| 895 | r13: bool = false, | ||
| 896 | r14: bool = false, | ||
| 897 | r15: bool = false, | ||
| 898 | r16: bool = false, | ||
| 899 | r17: bool = false, | ||
| 900 | r18: bool = false, | ||
| 901 | r19: bool = false, | ||
| 902 | r20: bool = false, | ||
| 903 | r21: bool = false, | ||
| 904 | r22: bool = false, | ||
| 905 | r23: bool = false, | ||
| 906 | r24: bool = false, | ||
| 907 | r25: bool = false, | ||
| 908 | r26: bool = false, | ||
| 909 | r27: bool = false, | ||
| 910 | r28: bool = false, | ||
| 911 | r29: bool = false, | ||
| 912 | r30: bool = false, | ||
| 913 | r31: bool = false, | ||
| 914 | }, | ||
| 915 | .avr => packed struct { | ||
| 916 | /// Whether the inline assembly code may perform stores to memory | ||
| 917 | /// addresses other than those derived from input pointer provenance. | ||
| 918 | memory: bool = false, | ||
| 919 | flags: bool = false, | ||
| 920 | r0: bool = false, | ||
| 921 | r1: bool = false, | ||
| 922 | r2: bool = false, | ||
| 923 | r3: bool = false, | ||
| 924 | r4: bool = false, | ||
| 925 | r5: bool = false, | ||
| 926 | r6: bool = false, | ||
| 927 | r7: bool = false, | ||
| 928 | r8: bool = false, | ||
| 929 | r9: bool = false, | ||
| 930 | r10: bool = false, | ||
| 931 | r11: bool = false, | ||
| 932 | r12: bool = false, | ||
| 933 | r13: bool = false, | ||
| 934 | r14: bool = false, | ||
| 935 | r15: bool = false, | ||
| 936 | r16: bool = false, | ||
| 937 | r17: bool = false, | ||
| 938 | r18: bool = false, | ||
| 939 | r19: bool = false, | ||
| 940 | r20: bool = false, | ||
| 941 | r21: bool = false, | ||
| 942 | r22: bool = false, | ||
| 943 | r23: bool = false, | ||
| 944 | r24: bool = false, | ||
| 945 | r25: bool = false, | ||
| 946 | r26: bool = false, | ||
| 947 | r27: bool = false, | ||
| 948 | r28: bool = false, | ||
| 949 | r29: bool = false, | ||
| 950 | r30: bool = false, | ||
| 951 | r31: bool = false, | ||
| 952 | }, | ||
| 953 | .msp430 => packed struct { | ||
| 954 | /// Whether the inline assembly code may perform stores to memory | ||
| 955 | /// addresses other than those derived from input pointer provenance. | ||
| 956 | memory: bool = false, | ||
| 957 | |||
| 958 | r0: bool = false, | ||
| 959 | r1: bool = false, | ||
| 960 | r2: bool = false, | ||
| 961 | |||
| 962 | r4: bool = false, | ||
| 963 | r5: bool = false, | ||
| 964 | r6: bool = false, | ||
| 965 | r7: bool = false, | ||
| 966 | r8: bool = false, | ||
| 967 | r9: bool = false, | ||
| 968 | r10: bool = false, | ||
| 969 | r11: bool = false, | ||
| 970 | r12: bool = false, | ||
| 971 | r13: bool = false, | ||
| 972 | r14: bool = false, | ||
| 973 | r15: bool = false, | ||
| 974 | }, | ||
| 975 | .m68k => packed struct { | ||
| 976 | /// Whether the inline assembly code may perform stores to memory | ||
| 977 | /// addresses other than those derived from input pointer provenance. | ||
| 978 | memory: bool = false, | ||
| 979 | |||
| 980 | ccr: bool = false, | ||
| 981 | |||
| 982 | d0: bool = false, | ||
| 983 | d1: bool = false, | ||
| 984 | d2: bool = false, | ||
| 985 | d3: bool = false, | ||
| 986 | d4: bool = false, | ||
| 987 | d5: bool = false, | ||
| 988 | d6: bool = false, | ||
| 989 | d7: bool = false, | ||
| 990 | |||
| 991 | a0: bool = false, | ||
| 992 | a1: bool = false, | ||
| 993 | a2: bool = false, | ||
| 994 | a3: bool = false, | ||
| 995 | a4: bool = false, | ||
| 996 | a5: bool = false, | ||
| 997 | a6: bool = false, | ||
| 998 | a7: bool = false, | ||
| 999 | |||
| 1000 | macsr: bool = false, | ||
| 1001 | acc: bool = false, | ||
| 1002 | |||
| 1003 | acc0: bool = false, | ||
| 1004 | acc1: bool = false, | ||
| 1005 | acc2: bool = false, | ||
| 1006 | acc3: bool = false, | ||
| 1007 | |||
| 1008 | mask: bool = false, | ||
| 1009 | fpcr: bool = false, | ||
| 1010 | fpsr: bool = false, | ||
| 1011 | |||
| 1012 | fp0: bool = false, | ||
| 1013 | fp1: bool = false, | ||
| 1014 | fp2: bool = false, | ||
| 1015 | fp3: bool = false, | ||
| 1016 | fp4: bool = false, | ||
| 1017 | fp5: bool = false, | ||
| 1018 | fp6: bool = false, | ||
| 1019 | fp7: bool = false, | ||
| 1020 | }, | ||
| 1021 | else => packed struct { | ||
| 1022 | /// Whether the inline assembly code may perform stores to memory | ||
| 1023 | /// addresses other than those derived from input pointer provenance. | ||
| 1024 | memory: bool = false, | ||
| 1025 | }, | ||
| 1026 | }; | ||
lib/std/zig.zig+2| ... | @@ -740,6 +740,7 @@ pub const SimpleComptimeReason = enum(u32) { | ... | @@ -740,6 +740,7 @@ pub const SimpleComptimeReason = enum(u32) { |
| 740 | generic_call_target, | 740 | generic_call_target, |
| 741 | wasm_memory_index, | 741 | wasm_memory_index, |
| 742 | work_group_dim_index, | 742 | work_group_dim_index, |
| 743 | clobber, | ||
| 743 | 744 | ||
| 744 | // Evaluating at comptime because types must be comptime-known. | 745 | // Evaluating at comptime because types must be comptime-known. |
| 745 | // Reasons other than `.type` are just more specific messages. | 746 | // Reasons other than `.type` are just more specific messages. |
| ... | @@ -820,6 +821,7 @@ pub const SimpleComptimeReason = enum(u32) { | ... | @@ -820,6 +821,7 @@ pub const SimpleComptimeReason = enum(u32) { |
| 820 | .generic_call_target => "generic function being called must be comptime-known", | 821 | .generic_call_target => "generic function being called must be comptime-known", |
| 821 | .wasm_memory_index => "wasm memory index must be comptime-known", | 822 | .wasm_memory_index => "wasm memory index must be comptime-known", |
| 822 | .work_group_dim_index => "work group dimension index must be comptime-known", | 823 | .work_group_dim_index => "work group dimension index must be comptime-known", |
| 824 | .clobber => "clobber must be comptime-known", | ||
| 823 | 825 | ||
| 824 | .type => "types must be comptime-known", | 826 | .type => "types must be comptime-known", |
| 825 | .array_sentinel => "array sentinel value must be comptime-known", | 827 | .array_sentinel => "array sentinel value must be comptime-known", |
lib/std/zig/Ast.zig+86-4| ... | @@ -634,6 +634,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { | ... | @@ -634,6 +634,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 634 | .@"nosuspend", | 634 | .@"nosuspend", |
| 635 | .asm_simple, | 635 | .asm_simple, |
| 636 | .@"asm", | 636 | .@"asm", |
| 637 | .asm_legacy, | ||
| 637 | .array_type, | 638 | .array_type, |
| 638 | .array_type_sentinel, | 639 | .array_type_sentinel, |
| 639 | .error_value, | 640 | .error_value, |
| ... | @@ -1047,6 +1048,11 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { | ... | @@ -1047,6 +1048,11 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1047 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | 1048 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter |
| 1048 | } | 1049 | } |
| 1049 | }, | 1050 | }, |
| 1051 | .asm_legacy => { | ||
| 1052 | _, const extra_index = tree.nodeData(n).node_and_extra; | ||
| 1053 | const extra = tree.extraData(extra_index, Node.AsmLegacy); | ||
| 1054 | return extra.rparen + end_offset; | ||
| 1055 | }, | ||
| 1050 | .@"asm" => { | 1056 | .@"asm" => { |
| 1051 | _, const extra_index = tree.nodeData(n).node_and_extra; | 1057 | _, const extra_index = tree.nodeData(n).node_and_extra; |
| 1052 | const extra = tree.extraData(extra_index, Node.Asm); | 1058 | const extra = tree.extraData(extra_index, Node.Asm); |
| ... | @@ -1885,6 +1891,19 @@ pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { | ... | @@ -1885,6 +1891,19 @@ pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { |
| 1885 | .template = template, | 1891 | .template = template, |
| 1886 | .items = &.{}, | 1892 | .items = &.{}, |
| 1887 | .rparen = rparen, | 1893 | .rparen = rparen, |
| 1894 | .clobbers = .none, | ||
| 1895 | }); | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | pub fn asmLegacy(tree: Ast, node: Node.Index) full.AsmLegacy { | ||
| 1899 | const template, const extra_index = tree.nodeData(node).node_and_extra; | ||
| 1900 | const extra = tree.extraData(extra_index, Node.AsmLegacy); | ||
| 1901 | const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index); | ||
| 1902 | return tree.legacyAsmComponents(.{ | ||
| 1903 | .asm_token = tree.nodeMainToken(node), | ||
| 1904 | .template = template, | ||
| 1905 | .items = items, | ||
| 1906 | .rparen = extra.rparen, | ||
| 1888 | }); | 1907 | }); |
| 1889 | } | 1908 | } |
| 1890 | 1909 | ||
| ... | @@ -1896,6 +1915,7 @@ pub fn asmFull(tree: Ast, node: Node.Index) full.Asm { | ... | @@ -1896,6 +1915,7 @@ pub fn asmFull(tree: Ast, node: Node.Index) full.Asm { |
| 1896 | .asm_token = tree.nodeMainToken(node), | 1915 | .asm_token = tree.nodeMainToken(node), |
| 1897 | .template = template, | 1916 | .template = template, |
| 1898 | .items = items, | 1917 | .items = items, |
| 1918 | .clobbers = extra.clobbers, | ||
| 1899 | .rparen = extra.rparen, | 1919 | .rparen = extra.rparen, |
| 1900 | }); | 1920 | }); |
| 1901 | } | 1921 | } |
| ... | @@ -2192,8 +2212,8 @@ fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: N | ... | @@ -2192,8 +2212,8 @@ fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: N |
| 2192 | return result; | 2212 | return result; |
| 2193 | } | 2213 | } |
| 2194 | 2214 | ||
| 2195 | fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { | 2215 | fn legacyAsmComponents(tree: Ast, info: full.AsmLegacy.Components) full.AsmLegacy { |
| 2196 | var result: full.Asm = .{ | 2216 | var result: full.AsmLegacy = .{ |
| 2197 | .ast = info, | 2217 | .ast = info, |
| 2198 | .volatile_token = null, | 2218 | .volatile_token = null, |
| 2199 | .inputs = &.{}, | 2219 | .inputs = &.{}, |
| ... | @@ -2253,6 +2273,29 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { | ... | @@ -2253,6 +2273,29 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2253 | return result; | 2273 | return result; |
| 2254 | } | 2274 | } |
| 2255 | 2275 | ||
| 2276 | fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { | ||
| 2277 | var result: full.Asm = .{ | ||
| 2278 | .ast = info, | ||
| 2279 | .volatile_token = null, | ||
| 2280 | .inputs = &.{}, | ||
| 2281 | .outputs = &.{}, | ||
| 2282 | }; | ||
| 2283 | if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) { | ||
| 2284 | result.volatile_token = info.asm_token + 1; | ||
| 2285 | } | ||
| 2286 | const outputs_end: usize = for (info.items, 0..) |item, i| { | ||
| 2287 | switch (tree.nodeTag(item)) { | ||
| 2288 | .asm_output => continue, | ||
| 2289 | else => break i, | ||
| 2290 | } | ||
| 2291 | } else info.items.len; | ||
| 2292 | |||
| 2293 | result.outputs = info.items[0..outputs_end]; | ||
| 2294 | result.inputs = info.items[outputs_end..]; | ||
| 2295 | |||
| 2296 | return result; | ||
| 2297 | } | ||
| 2298 | |||
| 2256 | fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { | 2299 | fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2257 | var result: full.While = .{ | 2300 | var result: full.While = .{ |
| 2258 | .ast = info, | 2301 | .ast = info, |
| ... | @@ -2447,6 +2490,14 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { | ... | @@ -2447,6 +2490,14 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { |
| 2447 | }; | 2490 | }; |
| 2448 | } | 2491 | } |
| 2449 | 2492 | ||
| 2493 | /// To be deleted after 0.15.0 is tagged | ||
| 2494 | pub fn legacyAsm(tree: Ast, node: Node.Index) ?full.AsmLegacy { | ||
| 2495 | return switch (tree.nodeTag(node)) { | ||
| 2496 | .asm_legacy => tree.asmLegacy(node), | ||
| 2497 | else => null, | ||
| 2498 | }; | ||
| 2499 | } | ||
| 2500 | |||
| 2450 | pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call { | 2501 | pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call { |
| 2451 | return switch (tree.nodeTag(node)) { | 2502 | return switch (tree.nodeTag(node)) { |
| 2452 | .call, .call_comma => tree.callFull(node), | 2503 | .call, .call_comma => tree.callFull(node), |
| ... | @@ -2827,6 +2878,21 @@ pub const full = struct { | ... | @@ -2827,6 +2878,21 @@ pub const full = struct { |
| 2827 | }; | 2878 | }; |
| 2828 | 2879 | ||
| 2829 | pub const Asm = struct { | 2880 | pub const Asm = struct { |
| 2881 | ast: Components, | ||
| 2882 | volatile_token: ?TokenIndex, | ||
| 2883 | outputs: []const Node.Index, | ||
| 2884 | inputs: []const Node.Index, | ||
| 2885 | |||
| 2886 | pub const Components = struct { | ||
| 2887 | asm_token: TokenIndex, | ||
| 2888 | template: Node.Index, | ||
| 2889 | items: []const Node.Index, | ||
| 2890 | clobbers: Node.OptionalIndex, | ||
| 2891 | rparen: TokenIndex, | ||
| 2892 | }; | ||
| 2893 | }; | ||
| 2894 | |||
| 2895 | pub const AsmLegacy = struct { | ||
| 2830 | ast: Components, | 2896 | ast: Components, |
| 2831 | volatile_token: ?TokenIndex, | 2897 | volatile_token: ?TokenIndex, |
| 2832 | first_clobber: ?TokenIndex, | 2898 | first_clobber: ?TokenIndex, |
| ... | @@ -3833,15 +3899,22 @@ pub const Node = struct { | ... | @@ -3833,15 +3899,22 @@ pub const Node = struct { |
| 3833 | /// Same as `block` except there is known to be a trailing comma before | 3899 | /// Same as `block` except there is known to be a trailing comma before |
| 3834 | /// the final rbrace. | 3900 | /// the final rbrace. |
| 3835 | block_semicolon, | 3901 | block_semicolon, |
| 3836 | /// `asm(lhs)`. | 3902 | /// `asm(a)`. |
| 3837 | /// | 3903 | /// |
| 3838 | /// rhs is a `Token.Index` to the `)` token. | ||
| 3839 | /// The `main_token` field is the `asm` token. | 3904 | /// The `main_token` field is the `asm` token. |
| 3840 | asm_simple, | 3905 | asm_simple, |
| 3841 | /// `asm(lhs, a)`. | 3906 | /// `asm(lhs, a)`. |
| 3842 | /// | 3907 | /// |
| 3843 | /// The `data` field is a `.node_and_extra`: | 3908 | /// The `data` field is a `.node_and_extra`: |
| 3844 | /// 1. a `Node.Index` to lhs. | 3909 | /// 1. a `Node.Index` to lhs. |
| 3910 | /// 2. a `ExtraIndex` to `AsmLegacy`. | ||
| 3911 | /// | ||
| 3912 | /// The `main_token` field is the `asm` token. | ||
| 3913 | asm_legacy, | ||
| 3914 | /// `asm(a, b)`. | ||
| 3915 | /// | ||
| 3916 | /// The `data` field is a `.node_and_extra`: | ||
| 3917 | /// 1. a `Node.Index` to a. | ||
| 3845 | /// 2. a `ExtraIndex` to `Asm`. | 3918 | /// 2. a `ExtraIndex` to `Asm`. |
| 3846 | /// | 3919 | /// |
| 3847 | /// The `main_token` field is the `asm` token. | 3920 | /// The `main_token` field is the `asm` token. |
| ... | @@ -4014,9 +4087,18 @@ pub const Node = struct { | ... | @@ -4014,9 +4087,18 @@ pub const Node = struct { |
| 4014 | callconv_expr: OptionalIndex, | 4087 | callconv_expr: OptionalIndex, |
| 4015 | }; | 4088 | }; |
| 4016 | 4089 | ||
| 4090 | /// To be removed after 0.15.0 is tagged | ||
| 4091 | pub const AsmLegacy = struct { | ||
| 4092 | items_start: ExtraIndex, | ||
| 4093 | items_end: ExtraIndex, | ||
| 4094 | /// Needed to make lastToken() work. | ||
| 4095 | rparen: TokenIndex, | ||
| 4096 | }; | ||
| 4097 | |||
| 4017 | pub const Asm = struct { | 4098 | pub const Asm = struct { |
| 4018 | items_start: ExtraIndex, | 4099 | items_start: ExtraIndex, |
| 4019 | items_end: ExtraIndex, | 4100 | items_end: ExtraIndex, |
| 4101 | clobbers: OptionalIndex, | ||
| 4020 | /// Needed to make lastToken() work. | 4102 | /// Needed to make lastToken() work. |
| 4021 | rparen: TokenIndex, | 4103 | rparen: TokenIndex, |
| 4022 | }; | 4104 | }; |
lib/std/zig/AstGen.zig+27-41| ... | @@ -505,6 +505,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins | ... | @@ -505,6 +505,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins |
| 505 | .bool_or, | 505 | .bool_or, |
| 506 | .@"asm", | 506 | .@"asm", |
| 507 | .asm_simple, | 507 | .asm_simple, |
| 508 | .asm_legacy, | ||
| 508 | .string_literal, | 509 | .string_literal, |
| 509 | .number_literal, | 510 | .number_literal, |
| 510 | .call, | 511 | .call, |
| ... | @@ -811,6 +812,12 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -811,6 +812,12 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 811 | .@"asm", | 812 | .@"asm", |
| 812 | => return asmExpr(gz, scope, ri, node, tree.fullAsm(node).?), | 813 | => return asmExpr(gz, scope, ri, node, tree.fullAsm(node).?), |
| 813 | 814 | ||
| 815 | .asm_legacy => { | ||
| 816 | return astgen.failNodeNotes(node, "legacy asm clobbers syntax", .{}, &[_]u32{ | ||
| 817 | try astgen.errNoteNode(node, "use 'zig fmt' to auto-upgrade", .{}), | ||
| 818 | }); | ||
| 819 | }, | ||
| 820 | |||
| 814 | .string_literal => return stringLiteral(gz, ri, node), | 821 | .string_literal => return stringLiteral(gz, ri, node), |
| 815 | .multiline_string_literal => return multilineStringLiteral(gz, ri, node), | 822 | .multiline_string_literal => return multilineStringLiteral(gz, ri, node), |
| 816 | 823 | ||
| ... | @@ -8774,7 +8781,7 @@ fn asmExpr( | ... | @@ -8774,7 +8781,7 @@ fn asmExpr( |
| 8774 | if (is_container_asm) { | 8781 | if (is_container_asm) { |
| 8775 | if (full.volatile_token) |t| | 8782 | if (full.volatile_token) |t| |
| 8776 | return astgen.failTok(t, "volatile is meaningless on global assembly", .{}); | 8783 | return astgen.failTok(t, "volatile is meaningless on global assembly", .{}); |
| 8777 | if (full.outputs.len != 0 or full.inputs.len != 0 or full.first_clobber != null) | 8784 | if (full.outputs.len != 0 or full.inputs.len != 0 or full.ast.clobbers != .none) |
| 8778 | return astgen.failNode(node, "global assembly cannot have inputs, outputs, or clobbers", .{}); | 8785 | return astgen.failNode(node, "global assembly cannot have inputs, outputs, or clobbers", .{}); |
| 8779 | } else { | 8786 | } else { |
| 8780 | if (full.outputs.len == 0 and full.volatile_token == null) { | 8787 | if (full.outputs.len == 0 and full.volatile_token == null) { |
| ... | @@ -8839,32 +8846,12 @@ fn asmExpr( | ... | @@ -8839,32 +8846,12 @@ fn asmExpr( |
| 8839 | }; | 8846 | }; |
| 8840 | } | 8847 | } |
| 8841 | 8848 | ||
| 8842 | var clobbers_buffer: [63]u32 = undefined; | 8849 | const clobbers: Zir.Inst.Ref = if (full.ast.clobbers.unwrap()) |clobbers_node| |
| 8843 | var clobber_i: usize = 0; | 8850 | try comptimeExpr(gz, scope, .{ .rl = .{ |
| 8844 | if (full.first_clobber) |first_clobber| clobbers: { | 8851 | .coerced_ty = try gz.addBuiltinValue(clobbers_node, .clobbers), |
| 8845 | // asm ("foo" ::: "a", "b") | 8852 | } }, clobbers_node, .clobber) |
| 8846 | // asm ("foo" ::: "a", "b",) | 8853 | else |
| 8847 | var tok_i = first_clobber; | 8854 | .none; |
| 8848 | while (true) : (tok_i += 1) { | ||
| 8849 | if (clobber_i >= clobbers_buffer.len) { | ||
| 8850 | return astgen.failTok(tok_i, "too many asm clobbers", .{}); | ||
| 8851 | } | ||
| 8852 | clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index); | ||
| 8853 | clobber_i += 1; | ||
| 8854 | tok_i += 1; | ||
| 8855 | switch (tree.tokenTag(tok_i)) { | ||
| 8856 | .r_paren => break :clobbers, | ||
| 8857 | .comma => { | ||
| 8858 | if (tree.tokenTag(tok_i + 1) == .r_paren) { | ||
| 8859 | break :clobbers; | ||
| 8860 | } else { | ||
| 8861 | continue; | ||
| 8862 | } | ||
| 8863 | }, | ||
| 8864 | else => unreachable, | ||
| 8865 | } | ||
| 8866 | } | ||
| 8867 | } | ||
| 8868 | 8855 | ||
| 8869 | const result = try gz.addAsm(.{ | 8856 | const result = try gz.addAsm(.{ |
| 8870 | .tag = tag_and_tmpl.tag, | 8857 | .tag = tag_and_tmpl.tag, |
| ... | @@ -8874,7 +8861,7 @@ fn asmExpr( | ... | @@ -8874,7 +8861,7 @@ fn asmExpr( |
| 8874 | .output_type_bits = output_type_bits, | 8861 | .output_type_bits = output_type_bits, |
| 8875 | .outputs = outputs, | 8862 | .outputs = outputs, |
| 8876 | .inputs = inputs, | 8863 | .inputs = inputs, |
| 8877 | .clobbers = clobbers_buffer[0..clobber_i], | 8864 | .clobbers = clobbers, |
| 8878 | }); | 8865 | }); |
| 8879 | return rvalue(gz, ri, result, node); | 8866 | return rvalue(gz, ri, result, node); |
| 8880 | } | 8867 | } |
| ... | @@ -10332,6 +10319,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev | ... | @@ -10332,6 +10319,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10332 | 10319 | ||
| 10333 | .@"asm", | 10320 | .@"asm", |
| 10334 | .asm_simple, | 10321 | .asm_simple, |
| 10322 | .asm_legacy, | ||
| 10335 | .identifier, | 10323 | .identifier, |
| 10336 | .field_access, | 10324 | .field_access, |
| 10337 | .deref, | 10325 | .deref, |
| ... | @@ -10575,6 +10563,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In | ... | @@ -10575,6 +10563,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 10575 | .tagged_union_enum_tag_trailing, | 10563 | .tagged_union_enum_tag_trailing, |
| 10576 | .@"asm", | 10564 | .@"asm", |
| 10577 | .asm_simple, | 10565 | .asm_simple, |
| 10566 | .asm_legacy, | ||
| 10578 | .add, | 10567 | .add, |
| 10579 | .add_wrap, | 10568 | .add_wrap, |
| 10580 | .add_sat, | 10569 | .add_sat, |
| ... | @@ -10813,6 +10802,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { | ... | @@ -10813,6 +10802,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10813 | .tagged_union_enum_tag_trailing, | 10802 | .tagged_union_enum_tag_trailing, |
| 10814 | .@"asm", | 10803 | .@"asm", |
| 10815 | .asm_simple, | 10804 | .asm_simple, |
| 10805 | .asm_legacy, | ||
| 10816 | .add, | 10806 | .add, |
| 10817 | .add_wrap, | 10807 | .add_wrap, |
| 10818 | .add_sat, | 10808 | .add_sat, |
| ... | @@ -12806,7 +12796,7 @@ const GenZir = struct { | ... | @@ -12806,7 +12796,7 @@ const GenZir = struct { |
| 12806 | is_volatile: bool, | 12796 | is_volatile: bool, |
| 12807 | outputs: []const Zir.Inst.Asm.Output, | 12797 | outputs: []const Zir.Inst.Asm.Output, |
| 12808 | inputs: []const Zir.Inst.Asm.Input, | 12798 | inputs: []const Zir.Inst.Asm.Input, |
| 12809 | clobbers: []const u32, | 12799 | clobbers: Zir.Inst.Ref, |
| 12810 | }, | 12800 | }, |
| 12811 | ) !Zir.Inst.Ref { | 12801 | ) !Zir.Inst.Ref { |
| 12812 | const astgen = gz.astgen; | 12802 | const astgen = gz.astgen; |
| ... | @@ -12816,13 +12806,13 @@ const GenZir = struct { | ... | @@ -12816,13 +12806,13 @@ const GenZir = struct { |
| 12816 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | 12806 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 12817 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).@"struct".fields.len + | 12807 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).@"struct".fields.len + |
| 12818 | args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).@"struct".fields.len + | 12808 | args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).@"struct".fields.len + |
| 12819 | args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).@"struct".fields.len + | 12809 | args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).@"struct".fields.len); |
| 12820 | args.clobbers.len); | ||
| 12821 | 12810 | ||
| 12822 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{ | 12811 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{ |
| 12823 | .src_node = gz.nodeIndexToRelative(args.node), | 12812 | .src_node = gz.nodeIndexToRelative(args.node), |
| 12824 | .asm_source = args.asm_source, | 12813 | .asm_source = args.asm_source, |
| 12825 | .output_type_bits = args.output_type_bits, | 12814 | .output_type_bits = args.output_type_bits, |
| 12815 | .clobbers = args.clobbers, | ||
| 12826 | }); | 12816 | }); |
| 12827 | for (args.outputs) |output| { | 12817 | for (args.outputs) |output| { |
| 12828 | _ = gz.astgen.addExtraAssumeCapacity(output); | 12818 | _ = gz.astgen.addExtraAssumeCapacity(output); |
| ... | @@ -12830,23 +12820,19 @@ const GenZir = struct { | ... | @@ -12830,23 +12820,19 @@ const GenZir = struct { |
| 12830 | for (args.inputs) |input| { | 12820 | for (args.inputs) |input| { |
| 12831 | _ = gz.astgen.addExtraAssumeCapacity(input); | 12821 | _ = gz.astgen.addExtraAssumeCapacity(input); |
| 12832 | } | 12822 | } |
| 12833 | gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers); | ||
| 12834 | 12823 | ||
| 12835 | // * 0b00000000_0000XXXX - `outputs_len`. | 12824 | const small: Zir.Inst.Asm.Small = .{ |
| 12836 | // * 0b0000000X_XXXX0000 - `inputs_len`. | 12825 | .outputs_len = @intCast(args.outputs.len), |
| 12837 | // * 0b0XXXXXX0_00000000 - `clobbers_len`. | 12826 | .inputs_len = @intCast(args.inputs.len), |
| 12838 | // * 0bX0000000_00000000 - is volatile | 12827 | .is_volatile = args.is_volatile, |
| 12839 | const small: u16 = @as(u16, @as(u4, @intCast(args.outputs.len))) << 0 | | 12828 | }; |
| 12840 | @as(u16, @as(u5, @intCast(args.inputs.len))) << 4 | | ||
| 12841 | @as(u16, @as(u6, @intCast(args.clobbers.len))) << 9 | | ||
| 12842 | @as(u16, @intFromBool(args.is_volatile)) << 15; | ||
| 12843 | 12829 | ||
| 12844 | const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); | 12830 | const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); |
| 12845 | astgen.instructions.appendAssumeCapacity(.{ | 12831 | astgen.instructions.appendAssumeCapacity(.{ |
| 12846 | .tag = .extended, | 12832 | .tag = .extended, |
| 12847 | .data = .{ .extended = .{ | 12833 | .data = .{ .extended = .{ |
| 12848 | .opcode = args.tag, | 12834 | .opcode = args.tag, |
| 12849 | .small = small, | 12835 | .small = @bitCast(small), |
| 12850 | .operand = payload_index, | 12836 | .operand = payload_index, |
| 12851 | } }, | 12837 | } }, |
| 12852 | }); | 12838 | }); |
lib/std/zig/AstRlAnnotate.zig+1| ... | @@ -310,6 +310,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI | ... | @@ -310,6 +310,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 310 | .unreachable_literal, | 310 | .unreachable_literal, |
| 311 | .asm_simple, | 311 | .asm_simple, |
| 312 | .@"asm", | 312 | .@"asm", |
| 313 | .asm_legacy, | ||
| 313 | .enum_literal, | 314 | .enum_literal, |
| 314 | .error_value, | 315 | .error_value, |
| 315 | .anyframe_literal, | 316 | .anyframe_literal, |
lib/std/zig/Parse.zig+27-4| ... | @@ -2801,7 +2801,7 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index { | ... | @@ -2801,7 +2801,7 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index { |
| 2801 | /// | 2801 | /// |
| 2802 | /// AsmInput <- COLON AsmInputList AsmClobbers? | 2802 | /// AsmInput <- COLON AsmInputList AsmClobbers? |
| 2803 | /// | 2803 | /// |
| 2804 | /// AsmClobbers <- COLON StringList | 2804 | /// AsmClobbers <- COLON Expr |
| 2805 | /// | 2805 | /// |
| 2806 | /// StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? | 2806 | /// StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL? |
| 2807 | /// | 2807 | /// |
| ... | @@ -2841,7 +2841,8 @@ fn expectAsmExpr(p: *Parse) !Node.Index { | ... | @@ -2841,7 +2841,8 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 2841 | else => try p.warnExpected(.comma), | 2841 | else => try p.warnExpected(.comma), |
| 2842 | } | 2842 | } |
| 2843 | } | 2843 | } |
| 2844 | if (p.eatToken(.colon)) |_| { | 2844 | |
| 2845 | const clobbers: Node.OptionalIndex = if (p.eatToken(.colon)) |_| clobbers: { | ||
| 2845 | while (true) { | 2846 | while (true) { |
| 2846 | const input_item = try p.parseAsmInputItem() orelse break; | 2847 | const input_item = try p.parseAsmInputItem() orelse break; |
| 2847 | try p.scratch.append(p.gpa, input_item); | 2848 | try p.scratch.append(p.gpa, input_item); |
| ... | @@ -2853,7 +2854,11 @@ fn expectAsmExpr(p: *Parse) !Node.Index { | ... | @@ -2853,7 +2854,11 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 2853 | else => try p.warnExpected(.comma), | 2854 | else => try p.warnExpected(.comma), |
| 2854 | } | 2855 | } |
| 2855 | } | 2856 | } |
| 2856 | if (p.eatToken(.colon)) |_| { | 2857 | |
| 2858 | _ = p.eatToken(.colon) orelse break :clobbers .none; | ||
| 2859 | |||
| 2860 | // For automatic upgrades; delete after 0.15.0 released. | ||
| 2861 | if (p.tokenTag(p.tok_i) == .string_literal) { | ||
| 2857 | while (p.eatToken(.string_literal)) |_| { | 2862 | while (p.eatToken(.string_literal)) |_| { |
| 2858 | switch (p.tokenTag(p.tok_i)) { | 2863 | switch (p.tokenTag(p.tok_i)) { |
| 2859 | .comma => p.tok_i += 1, | 2864 | .comma => p.tok_i += 1, |
| ... | @@ -2862,8 +2867,25 @@ fn expectAsmExpr(p: *Parse) !Node.Index { | ... | @@ -2862,8 +2867,25 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 2862 | else => try p.warnExpected(.comma), | 2867 | else => try p.warnExpected(.comma), |
| 2863 | } | 2868 | } |
| 2864 | } | 2869 | } |
| 2870 | const rparen = try p.expectToken(.r_paren); | ||
| 2871 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); | ||
| 2872 | return p.addNode(.{ | ||
| 2873 | .tag = .asm_legacy, | ||
| 2874 | .main_token = asm_token, | ||
| 2875 | .data = .{ .node_and_extra = .{ | ||
| 2876 | template, | ||
| 2877 | try p.addExtra(Node.AsmLegacy{ | ||
| 2878 | .items_start = span.start, | ||
| 2879 | .items_end = span.end, | ||
| 2880 | .rparen = rparen, | ||
| 2881 | }), | ||
| 2882 | } }, | ||
| 2883 | }); | ||
| 2865 | } | 2884 | } |
| 2866 | } | 2885 | |
| 2886 | break :clobbers (try p.expectExpr()).toOptional(); | ||
| 2887 | } else .none; | ||
| 2888 | |||
| 2867 | const rparen = try p.expectToken(.r_paren); | 2889 | const rparen = try p.expectToken(.r_paren); |
| 2868 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); | 2890 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2869 | return p.addNode(.{ | 2891 | return p.addNode(.{ |
| ... | @@ -2874,6 +2896,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index { | ... | @@ -2874,6 +2896,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 2874 | try p.addExtra(Node.Asm{ | 2896 | try p.addExtra(Node.Asm{ |
| 2875 | .items_start = span.start, | 2897 | .items_start = span.start, |
| 2876 | .items_end = span.end, | 2898 | .items_end = span.end, |
| 2899 | .clobbers = clobbers, | ||
| 2877 | .rparen = rparen, | 2900 | .rparen = rparen, |
| 2878 | }), | 2901 | }), |
| 2879 | } }, | 2902 | } }, |
lib/std/zig/Zir.zig+8-6| ... | @@ -1939,11 +1939,6 @@ pub const Inst = struct { | ... | @@ -1939,11 +1939,6 @@ pub const Inst = struct { |
| 1939 | /// `operand` is payload index to `BinNode`. | 1939 | /// `operand` is payload index to `BinNode`. |
| 1940 | builtin_extern, | 1940 | builtin_extern, |
| 1941 | /// Inline assembly. | 1941 | /// Inline assembly. |
| 1942 | /// `small`: | ||
| 1943 | /// * 0b00000000_000XXXXX - `outputs_len`. | ||
| 1944 | /// * 0b000000XX_XXX00000 - `inputs_len`. | ||
| 1945 | /// * 0b0XXXXX00_00000000 - `clobbers_len`. | ||
| 1946 | /// * 0bX0000000_00000000 - is volatile | ||
| 1947 | /// `operand` is payload index to `Asm`. | 1942 | /// `operand` is payload index to `Asm`. |
| 1948 | @"asm", | 1943 | @"asm", |
| 1949 | /// Same as `asm` except the assembly template is not a string literal but a comptime | 1944 | /// Same as `asm` except the assembly template is not a string literal but a comptime |
| ... | @@ -2495,7 +2490,6 @@ pub const Inst = struct { | ... | @@ -2495,7 +2490,6 @@ pub const Inst = struct { |
| 2495 | /// Trailing: | 2490 | /// Trailing: |
| 2496 | /// 0. Output for every outputs_len | 2491 | /// 0. Output for every outputs_len |
| 2497 | /// 1. Input for every inputs_len | 2492 | /// 1. Input for every inputs_len |
| 2498 | /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len. | ||
| 2499 | pub const Asm = struct { | 2493 | pub const Asm = struct { |
| 2500 | src_node: Ast.Node.Offset, | 2494 | src_node: Ast.Node.Offset, |
| 2501 | // null-terminated string index | 2495 | // null-terminated string index |
| ... | @@ -2505,6 +2499,13 @@ pub const Inst = struct { | ... | @@ -2505,6 +2499,13 @@ pub const Inst = struct { |
| 2505 | /// 0b1 - operand is a type; asm expression has the output as the result. | 2499 | /// 0b1 - operand is a type; asm expression has the output as the result. |
| 2506 | /// 0b0X is the first output, 0bX0 is the second, etc. | 2500 | /// 0b0X is the first output, 0bX0 is the second, etc. |
| 2507 | output_type_bits: u32, | 2501 | output_type_bits: u32, |
| 2502 | clobbers: Ref, | ||
| 2503 | |||
| 2504 | pub const Small = packed struct(u16) { | ||
| 2505 | is_volatile: bool, | ||
| 2506 | outputs_len: u7, | ||
| 2507 | inputs_len: u8, | ||
| 2508 | }; | ||
| 2508 | 2509 | ||
| 2509 | pub const Output = struct { | 2510 | pub const Output = struct { |
| 2510 | /// index into string_bytes (null terminated) | 2511 | /// index into string_bytes (null terminated) |
| ... | @@ -3482,6 +3483,7 @@ pub const Inst = struct { | ... | @@ -3482,6 +3483,7 @@ pub const Inst = struct { |
| 3482 | extern_options, | 3483 | extern_options, |
| 3483 | type_info, | 3484 | type_info, |
| 3484 | branch_hint, | 3485 | branch_hint, |
| 3486 | clobbers, | ||
| 3485 | // Values | 3487 | // Values |
| 3486 | calling_convention_c, | 3488 | calling_convention_c, |
| 3487 | calling_convention_inline, | 3489 | calling_convention_inline, |
lib/std/zig/ZonGen.zig+1-1| ... | @@ -227,7 +227,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator | ... | @@ -227,7 +227,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 227 | => try zg.addErrorNode(node, "control flow is not allowed in ZON", .{}), | 227 | => try zg.addErrorNode(node, "control flow is not allowed in ZON", .{}), |
| 228 | 228 | ||
| 229 | .@"comptime" => try zg.addErrorNode(node, "keyword 'comptime' is not allowed in ZON", .{}), | 229 | .@"comptime" => try zg.addErrorNode(node, "keyword 'comptime' is not allowed in ZON", .{}), |
| 230 | .asm_simple, .@"asm" => try zg.addErrorNode(node, "inline asm is not allowed in ZON", .{}), | 230 | .asm_simple, .@"asm", .asm_legacy => try zg.addErrorNode(node, "inline asm is not allowed in ZON", .{}), |
| 231 | 231 | ||
| 232 | .builtin_call_two, | 232 | .builtin_call_two, |
| 233 | .builtin_call_two_comma, | 233 | .builtin_call_two_comma, |
lib/std/zig/render.zig+150-10| ... | @@ -852,6 +852,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { | ... | @@ -852,6 +852,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 852 | .@"asm", | 852 | .@"asm", |
| 853 | => return renderAsm(r, tree.fullAsm(node).?, space), | 853 | => return renderAsm(r, tree.fullAsm(node).?, space), |
| 854 | 854 | ||
| 855 | // To be removed after 0.15.0 is tagged | ||
| 856 | .asm_legacy => return renderAsmLegacy(r, tree.legacyAsm(node).?, space), | ||
| 857 | |||
| 855 | .enum_literal => { | 858 | .enum_literal => { |
| 856 | try renderToken(r, tree.nodeMainToken(node) - 1, .none); // . | 859 | try renderToken(r, tree.nodeMainToken(node) - 1, .none); // . |
| 857 | return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name | 860 | return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name |
| ... | @@ -2363,9 +2366,9 @@ fn renderContainerDecl( | ... | @@ -2363,9 +2366,9 @@ fn renderContainerDecl( |
| 2363 | return renderToken(r, rbrace, space); // rbrace | 2366 | return renderToken(r, rbrace, space); // rbrace |
| 2364 | } | 2367 | } |
| 2365 | 2368 | ||
| 2366 | fn renderAsm( | 2369 | fn renderAsmLegacy( |
| 2367 | r: *Render, | 2370 | r: *Render, |
| 2368 | asm_node: Ast.full.Asm, | 2371 | asm_node: Ast.full.AsmLegacy, |
| 2369 | space: Space, | 2372 | space: Space, |
| 2370 | ) Error!void { | 2373 | ) Error!void { |
| 2371 | const tree = r.tree; | 2374 | const tree = r.tree; |
| ... | @@ -2391,12 +2394,17 @@ fn renderAsm( | ... | @@ -2391,12 +2394,17 @@ fn renderAsm( |
| 2391 | try renderToken(r, first_clobber - 2, .none); | 2394 | try renderToken(r, first_clobber - 2, .none); |
| 2392 | try renderToken(r, first_clobber - 1, .space); | 2395 | try renderToken(r, first_clobber - 1, .space); |
| 2393 | 2396 | ||
| 2397 | try ais.writer().writeAll(".{ "); | ||
| 2398 | |||
| 2394 | var tok_i = first_clobber; | 2399 | var tok_i = first_clobber; |
| 2395 | while (true) : (tok_i += 1) { | 2400 | while (true) : (tok_i += 1) { |
| 2396 | try renderToken(r, tok_i, .none); | 2401 | try ais.writer().writeAll(".@"); |
| 2402 | try ais.writer().writeAll(tokenSliceForRender(tree, tok_i)); | ||
| 2403 | |||
| 2397 | tok_i += 1; | 2404 | tok_i += 1; |
| 2398 | switch (tree.tokenTag(tok_i)) { | 2405 | switch (tree.tokenTag(tok_i)) { |
| 2399 | .r_paren => { | 2406 | .r_paren => { |
| 2407 | try ais.writer().writeAll(" }"); | ||
| 2400 | ais.popIndent(); | 2408 | ais.popIndent(); |
| 2401 | return renderToken(r, tok_i, space); | 2409 | return renderToken(r, tok_i, space); |
| 2402 | }, | 2410 | }, |
| ... | @@ -2412,10 +2420,7 @@ fn renderAsm( | ... | @@ -2412,10 +2420,7 @@ fn renderAsm( |
| 2412 | } | 2420 | } |
| 2413 | } | 2421 | } |
| 2414 | } else { | 2422 | } else { |
| 2415 | // asm ("foo") | 2423 | unreachable; |
| 2416 | try renderExpression(r, asm_node.ast.template, .none); | ||
| 2417 | ais.popIndent(); | ||
| 2418 | return renderToken(r, asm_node.ast.rparen, space); // rparen | ||
| 2419 | } | 2424 | } |
| 2420 | } | 2425 | } |
| 2421 | 2426 | ||
| ... | @@ -2499,13 +2504,18 @@ fn renderAsm( | ... | @@ -2499,13 +2504,18 @@ fn renderAsm( |
| 2499 | }; | 2504 | }; |
| 2500 | 2505 | ||
| 2501 | try renderToken(r, colon3, .space); // : | 2506 | try renderToken(r, colon3, .space); // : |
| 2507 | try ais.writer().writeAll(".{ "); | ||
| 2502 | const first_clobber = asm_node.first_clobber.?; | 2508 | const first_clobber = asm_node.first_clobber.?; |
| 2503 | var tok_i = first_clobber; | 2509 | var tok_i = first_clobber; |
| 2504 | while (true) { | 2510 | while (true) { |
| 2505 | switch (tree.tokenTag(tok_i + 1)) { | 2511 | switch (tree.tokenTag(tok_i + 1)) { |
| 2506 | .r_paren => { | 2512 | .r_paren => { |
| 2507 | ais.setIndentDelta(indent_delta); | 2513 | ais.setIndentDelta(indent_delta); |
| 2508 | try renderToken(r, tok_i, .newline); | 2514 | try ais.writer().writeAll(".@"); |
| 2515 | const lexeme = tokenSliceForRender(tree, tok_i); | ||
| 2516 | try ais.writer().writeAll(lexeme); | ||
| 2517 | try ais.writer().writeAll(" }"); | ||
| 2518 | try renderSpace(r, tok_i, lexeme.len, .newline); | ||
| 2509 | ais.popIndent(); | 2519 | ais.popIndent(); |
| 2510 | return renderToken(r, tok_i + 1, space); | 2520 | return renderToken(r, tok_i + 1, space); |
| 2511 | }, | 2521 | }, |
| ... | @@ -2513,12 +2523,17 @@ fn renderAsm( | ... | @@ -2513,12 +2523,17 @@ fn renderAsm( |
| 2513 | switch (tree.tokenTag(tok_i + 2)) { | 2523 | switch (tree.tokenTag(tok_i + 2)) { |
| 2514 | .r_paren => { | 2524 | .r_paren => { |
| 2515 | ais.setIndentDelta(indent_delta); | 2525 | ais.setIndentDelta(indent_delta); |
| 2516 | try renderToken(r, tok_i, .newline); | 2526 | try ais.writer().writeAll(".@"); |
| 2527 | const lexeme = tokenSliceForRender(tree, tok_i); | ||
| 2528 | try ais.writer().writeAll(lexeme); | ||
| 2529 | try ais.writer().writeAll(" }"); | ||
| 2530 | try renderSpace(r, tok_i, lexeme.len, .newline); | ||
| 2517 | ais.popIndent(); | 2531 | ais.popIndent(); |
| 2518 | return renderToken(r, tok_i + 2, space); | 2532 | return renderToken(r, tok_i + 2, space); |
| 2519 | }, | 2533 | }, |
| 2520 | else => { | 2534 | else => { |
| 2521 | try renderToken(r, tok_i, .none); | 2535 | try ais.writer().writeAll(".@"); |
| 2536 | try ais.writer().writeAll(tokenSliceForRender(tree, tok_i)); | ||
| 2522 | try renderToken(r, tok_i + 1, .space); | 2537 | try renderToken(r, tok_i + 1, .space); |
| 2523 | tok_i += 2; | 2538 | tok_i += 2; |
| 2524 | }, | 2539 | }, |
| ... | @@ -2529,6 +2544,131 @@ fn renderAsm( | ... | @@ -2529,6 +2544,131 @@ fn renderAsm( |
| 2529 | } | 2544 | } |
| 2530 | } | 2545 | } |
| 2531 | 2546 | ||
| 2547 | fn renderAsm( | ||
| 2548 | r: *Render, | ||
| 2549 | asm_node: Ast.full.Asm, | ||
| 2550 | space: Space, | ||
| 2551 | ) Error!void { | ||
| 2552 | const tree = r.tree; | ||
| 2553 | const ais = r.ais; | ||
| 2554 | |||
| 2555 | try renderToken(r, asm_node.ast.asm_token, .space); // asm | ||
| 2556 | |||
| 2557 | if (asm_node.volatile_token) |volatile_token| { | ||
| 2558 | try renderToken(r, volatile_token, .space); // volatile | ||
| 2559 | try renderToken(r, volatile_token + 1, .none); // lparen | ||
| 2560 | } else { | ||
| 2561 | try renderToken(r, asm_node.ast.asm_token + 1, .none); // lparen | ||
| 2562 | } | ||
| 2563 | |||
| 2564 | if (asm_node.ast.items.len == 0) { | ||
| 2565 | try ais.forcePushIndent(.normal); | ||
| 2566 | if (asm_node.ast.clobbers.unwrap()) |clobbers| { | ||
| 2567 | // asm ("foo" ::: clobbers) | ||
| 2568 | try renderExpression(r, asm_node.ast.template, .space); | ||
| 2569 | // Render the three colons. | ||
| 2570 | const first_clobber = tree.firstToken(clobbers); | ||
| 2571 | try renderToken(r, first_clobber - 3, .none); | ||
| 2572 | try renderToken(r, first_clobber - 2, .none); | ||
| 2573 | try renderToken(r, first_clobber - 1, .space); | ||
| 2574 | try renderExpression(r, clobbers, .none); | ||
| 2575 | ais.popIndent(); | ||
| 2576 | return renderToken(r, asm_node.ast.rparen, space); // rparen | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | // asm ("foo") | ||
| 2580 | try renderExpression(r, asm_node.ast.template, .none); | ||
| 2581 | ais.popIndent(); | ||
| 2582 | return renderToken(r, asm_node.ast.rparen, space); // rparen | ||
| 2583 | } | ||
| 2584 | |||
| 2585 | try ais.forcePushIndent(.normal); | ||
| 2586 | try renderExpression(r, asm_node.ast.template, .newline); | ||
| 2587 | ais.setIndentDelta(asm_indent_delta); | ||
| 2588 | const colon1 = tree.lastToken(asm_node.ast.template) + 1; | ||
| 2589 | |||
| 2590 | const colon2 = if (asm_node.outputs.len == 0) colon2: { | ||
| 2591 | try renderToken(r, colon1, .newline); // : | ||
| 2592 | break :colon2 colon1 + 1; | ||
| 2593 | } else colon2: { | ||
| 2594 | try renderToken(r, colon1, .space); // : | ||
| 2595 | |||
| 2596 | try ais.forcePushIndent(.normal); | ||
| 2597 | for (asm_node.outputs, 0..) |asm_output, i| { | ||
| 2598 | if (i + 1 < asm_node.outputs.len) { | ||
| 2599 | const next_asm_output = asm_node.outputs[i + 1]; | ||
| 2600 | try renderAsmOutput(r, asm_output, .none); | ||
| 2601 | |||
| 2602 | const comma = tree.firstToken(next_asm_output) - 1; | ||
| 2603 | try renderToken(r, comma, .newline); // , | ||
| 2604 | try renderExtraNewlineToken(r, tree.firstToken(next_asm_output)); | ||
| 2605 | } else if (asm_node.inputs.len == 0 and asm_node.ast.clobbers == .none) { | ||
| 2606 | try ais.pushSpace(.comma); | ||
| 2607 | try renderAsmOutput(r, asm_output, .comma); | ||
| 2608 | ais.popSpace(); | ||
| 2609 | ais.popIndent(); | ||
| 2610 | ais.setIndentDelta(indent_delta); | ||
| 2611 | ais.popIndent(); | ||
| 2612 | return renderToken(r, asm_node.ast.rparen, space); // rparen | ||
| 2613 | } else { | ||
| 2614 | try ais.pushSpace(.comma); | ||
| 2615 | try renderAsmOutput(r, asm_output, .comma); | ||
| 2616 | ais.popSpace(); | ||
| 2617 | const comma_or_colon = tree.lastToken(asm_output) + 1; | ||
| 2618 | ais.popIndent(); | ||
| 2619 | break :colon2 switch (tree.tokenTag(comma_or_colon)) { | ||
| 2620 | .comma => comma_or_colon + 1, | ||
| 2621 | else => comma_or_colon, | ||
| 2622 | }; | ||
| 2623 | } | ||
| 2624 | } else unreachable; | ||
| 2625 | }; | ||
| 2626 | |||
| 2627 | const colon3 = if (asm_node.inputs.len == 0) colon3: { | ||
| 2628 | try renderToken(r, colon2, .newline); // : | ||
| 2629 | break :colon3 colon2 + 1; | ||
| 2630 | } else colon3: { | ||
| 2631 | try renderToken(r, colon2, .space); // : | ||
| 2632 | try ais.forcePushIndent(.normal); | ||
| 2633 | for (asm_node.inputs, 0..) |asm_input, i| { | ||
| 2634 | if (i + 1 < asm_node.inputs.len) { | ||
| 2635 | const next_asm_input = asm_node.inputs[i + 1]; | ||
| 2636 | try renderAsmInput(r, asm_input, .none); | ||
| 2637 | |||
| 2638 | const first_token = tree.firstToken(next_asm_input); | ||
| 2639 | try renderToken(r, first_token - 1, .newline); // , | ||
| 2640 | try renderExtraNewlineToken(r, first_token); | ||
| 2641 | } else if (asm_node.ast.clobbers == .none) { | ||
| 2642 | try ais.pushSpace(.comma); | ||
| 2643 | try renderAsmInput(r, asm_input, .comma); | ||
| 2644 | ais.popSpace(); | ||
| 2645 | ais.popIndent(); | ||
| 2646 | ais.setIndentDelta(indent_delta); | ||
| 2647 | ais.popIndent(); | ||
| 2648 | return renderToken(r, asm_node.ast.rparen, space); // rparen | ||
| 2649 | } else { | ||
| 2650 | try ais.pushSpace(.comma); | ||
| 2651 | try renderAsmInput(r, asm_input, .comma); | ||
| 2652 | ais.popSpace(); | ||
| 2653 | const comma_or_colon = tree.lastToken(asm_input) + 1; | ||
| 2654 | ais.popIndent(); | ||
| 2655 | break :colon3 switch (tree.tokenTag(comma_or_colon)) { | ||
| 2656 | .comma => comma_or_colon + 1, | ||
| 2657 | else => comma_or_colon, | ||
| 2658 | }; | ||
| 2659 | } | ||
| 2660 | } | ||
| 2661 | unreachable; | ||
| 2662 | }; | ||
| 2663 | |||
| 2664 | try renderToken(r, colon3, .space); // : | ||
| 2665 | const clobbers = asm_node.ast.clobbers.unwrap().?; | ||
| 2666 | try renderExpression(r, clobbers, .none); | ||
| 2667 | ais.setIndentDelta(indent_delta); | ||
| 2668 | ais.popIndent(); | ||
| 2669 | return renderToken(r, asm_node.ast.rparen, space); // rparen | ||
| 2670 | } | ||
| 2671 | |||
| 2532 | fn renderCall( | 2672 | fn renderCall( |
| 2533 | r: *Render, | 2673 | r: *Render, |
| 2534 | call: Ast.full.Call, | 2674 | call: Ast.full.Call, |
src/Air.zig+10-9| ... | @@ -1413,19 +1413,20 @@ pub const ShuffleTwoMask = enum(u32) { | ... | @@ -1413,19 +1413,20 @@ pub const ShuffleTwoMask = enum(u32) { |
| 1413 | /// terminated string. | 1413 | /// terminated string. |
| 1414 | /// - name: memory at this position is reinterpreted as a null | 1414 | /// - name: memory at this position is reinterpreted as a null |
| 1415 | /// terminated string. pad to the next u32 after the null byte. | 1415 | /// terminated string. pad to the next u32 after the null byte. |
| 1416 | /// 4. for every clobbers_len | 1416 | /// 4. A number of u32 elements follow according to the equation `(source_len + 3) / 4`. |
| 1417 | /// - clobber_name: memory at this position is reinterpreted as a null | ||
| 1418 | /// terminated string. pad to the next u32 after the null byte. | ||
| 1419 | /// 5. A number of u32 elements follow according to the equation `(source_len + 3) / 4`. | ||
| 1420 | /// Memory starting at this position is reinterpreted as the source bytes. | 1417 | /// Memory starting at this position is reinterpreted as the source bytes. |
| 1421 | pub const Asm = struct { | 1418 | pub const Asm = struct { |
| 1422 | /// Length of the assembly source in bytes. | 1419 | /// Length of the assembly source in bytes. |
| 1423 | source_len: u32, | 1420 | source_len: u32, |
| 1424 | outputs_len: u32, | ||
| 1425 | inputs_len: u32, | 1421 | inputs_len: u32, |
| 1426 | /// The MSB is `is_volatile`. | 1422 | /// A comptime `std.builtin.assembly.Clobbers` value for the target architecture. |
| 1427 | /// The rest of the bits are `clobbers_len`. | 1423 | clobbers: InternPool.Index, |
| 1428 | flags: u32, | 1424 | flags: Flags, |
| 1425 | |||
| 1426 | pub const Flags = packed struct(u32) { | ||
| 1427 | outputs_len: u31, | ||
| 1428 | is_volatile: bool, | ||
| 1429 | }; | ||
| 1429 | }; | 1430 | }; |
| 1430 | 1431 | ||
| 1431 | pub const Cmpxchg = struct { | 1432 | pub const Cmpxchg = struct { |
| ... | @@ -1749,7 +1750,7 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end | ... | @@ -1749,7 +1750,7 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end |
| 1749 | @field(result, field.name) = switch (field.type) { | 1750 | @field(result, field.name) = switch (field.type) { |
| 1750 | u32 => air.extra.items[i], | 1751 | u32 => air.extra.items[i], |
| 1751 | InternPool.Index, Inst.Ref => @enumFromInt(air.extra.items[i]), | 1752 | InternPool.Index, Inst.Ref => @enumFromInt(air.extra.items[i]), |
| 1752 | i32, CondBr.BranchHints => @bitCast(air.extra.items[i]), | 1753 | i32, CondBr.BranchHints, Asm.Flags => @bitCast(air.extra.items[i]), |
| 1753 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 1754 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 1754 | }; | 1755 | }; |
| 1755 | i += 1; | 1756 | i += 1; |
src/Air/Liveness.zig+2-1| ... | @@ -1208,8 +1208,9 @@ fn analyzeInst( | ... | @@ -1208,8 +1208,9 @@ fn analyzeInst( |
| 1208 | 1208 | ||
| 1209 | .assembly => { | 1209 | .assembly => { |
| 1210 | const extra = a.air.extraData(Air.Asm, inst_datas[@intFromEnum(inst)].ty_pl.payload); | 1210 | const extra = a.air.extraData(Air.Asm, inst_datas[@intFromEnum(inst)].ty_pl.payload); |
| 1211 | const outputs_len = extra.data.flags.outputs_len; | ||
| 1211 | var extra_i: usize = extra.end; | 1212 | var extra_i: usize = extra.end; |
| 1212 | const outputs = @as([]const Air.Inst.Ref, @ptrCast(a.air.extra.items[extra_i..][0..extra.data.outputs_len])); | 1213 | const outputs = @as([]const Air.Inst.Ref, @ptrCast(a.air.extra.items[extra_i..][0..outputs_len])); |
| 1213 | extra_i += outputs.len; | 1214 | extra_i += outputs.len; |
| 1214 | const inputs = @as([]const Air.Inst.Ref, @ptrCast(a.air.extra.items[extra_i..][0..extra.data.inputs_len])); | 1215 | const inputs = @as([]const Air.Inst.Ref, @ptrCast(a.air.extra.items[extra_i..][0..extra.data.inputs_len])); |
| 1215 | extra_i += inputs.len; | 1216 | extra_i += inputs.len; |
src/Air/Liveness/Verify.zig+3-8| ... | @@ -366,16 +366,11 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { | ... | @@ -366,16 +366,11 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 366 | .assembly => { | 366 | .assembly => { |
| 367 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | 367 | const ty_pl = data[@intFromEnum(inst)].ty_pl; |
| 368 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); | 368 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 369 | const outputs_len = extra.data.flags.outputs_len; | ||
| 369 | var extra_i = extra.end; | 370 | var extra_i = extra.end; |
| 370 | const outputs = @as( | 371 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..outputs_len]); |
| 371 | []const Air.Inst.Ref, | ||
| 372 | @ptrCast(self.air.extra.items[extra_i..][0..extra.data.outputs_len]), | ||
| 373 | ); | ||
| 374 | extra_i += outputs.len; | 372 | extra_i += outputs.len; |
| 375 | const inputs = @as( | 373 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); |
| 376 | []const Air.Inst.Ref, | ||
| 377 | @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]), | ||
| 378 | ); | ||
| 379 | extra_i += inputs.len; | 374 | extra_i += inputs.len; |
| 380 | 375 | ||
| 381 | var bt = self.liveness.iterateBigTomb(inst); | 376 | var bt = self.liveness.iterateBigTomb(inst); |
src/Air/print.zig+35-18| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Allocator = std.mem.Allocator; | 2 | const Allocator = std.mem.Allocator; |
| 3 | const assert = std.debug.assert; | ||
| 3 | 4 | ||
| 4 | const build_options = @import("build_options"); | 5 | const build_options = @import("build_options"); |
| 5 | const Zcu = @import("../Zcu.zig"); | 6 | const Zcu = @import("../Zcu.zig"); |
| ... | @@ -9,7 +10,7 @@ const Air = @import("../Air.zig"); | ... | @@ -9,7 +10,7 @@ const Air = @import("../Air.zig"); |
| 9 | const InternPool = @import("../InternPool.zig"); | 10 | const InternPool = @import("../InternPool.zig"); |
| 10 | 11 | ||
| 11 | pub fn write(air: Air, stream: *std.io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | 12 | pub fn write(air: Air, stream: *std.io.Writer, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { |
| 12 | comptime std.debug.assert(build_options.enable_debug_extensions); | 13 | comptime assert(build_options.enable_debug_extensions); |
| 13 | const instruction_bytes = air.instructions.len * | 14 | const instruction_bytes = air.instructions.len * |
| 14 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | 15 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include |
| 15 | // the debug safety tag but we want to measure release size. | 16 | // the debug safety tag but we want to measure release size. |
| ... | @@ -59,7 +60,7 @@ pub fn writeInst( | ... | @@ -59,7 +60,7 @@ pub fn writeInst( |
| 59 | pt: Zcu.PerThread, | 60 | pt: Zcu.PerThread, |
| 60 | liveness: ?Air.Liveness, | 61 | liveness: ?Air.Liveness, |
| 61 | ) void { | 62 | ) void { |
| 62 | comptime std.debug.assert(build_options.enable_debug_extensions); | 63 | comptime assert(build_options.enable_debug_extensions); |
| 63 | var writer: Writer = .{ | 64 | var writer: Writer = .{ |
| 64 | .pt = pt, | 65 | .pt = pt, |
| 65 | .gpa = pt.zcu.gpa, | 66 | .gpa = pt.zcu.gpa, |
| ... | @@ -643,8 +644,8 @@ const Writer = struct { | ... | @@ -643,8 +644,8 @@ const Writer = struct { |
| 643 | fn writeAssembly(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void { | 644 | fn writeAssembly(w: *Writer, s: *std.io.Writer, inst: Air.Inst.Index) Error!void { |
| 644 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 645 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 645 | const extra = w.air.extraData(Air.Asm, ty_pl.payload); | 646 | const extra = w.air.extraData(Air.Asm, ty_pl.payload); |
| 646 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | 647 | const is_volatile = extra.data.flags.is_volatile; |
| 647 | const clobbers_len = @as(u31, @truncate(extra.data.flags)); | 648 | const outputs_len = extra.data.flags.outputs_len; |
| 648 | var extra_i: usize = extra.end; | 649 | var extra_i: usize = extra.end; |
| 649 | var op_index: usize = 0; | 650 | var op_index: usize = 0; |
| 650 | 651 | ||
| ... | @@ -655,7 +656,7 @@ const Writer = struct { | ... | @@ -655,7 +656,7 @@ const Writer = struct { |
| 655 | try s.writeAll(", volatile"); | 656 | try s.writeAll(", volatile"); |
| 656 | } | 657 | } |
| 657 | 658 | ||
| 658 | const outputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.outputs_len])); | 659 | const outputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..outputs_len])); |
| 659 | extra_i += outputs.len; | 660 | extra_i += outputs.len; |
| 660 | const inputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.inputs_len])); | 661 | const inputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.inputs_len])); |
| 661 | extra_i += inputs.len; | 662 | extra_i += inputs.len; |
| ... | @@ -695,19 +696,35 @@ const Writer = struct { | ... | @@ -695,19 +696,35 @@ const Writer = struct { |
| 695 | try s.writeByte(')'); | 696 | try s.writeByte(')'); |
| 696 | } | 697 | } |
| 697 | 698 | ||
| 698 | { | 699 | const zcu = w.pt.zcu; |
| 699 | var clobber_i: u32 = 0; | 700 | const ip = &zcu.intern_pool; |
| 700 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | 701 | const aggregate = ip.indexToKey(extra.data.clobbers).aggregate; |
| 701 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | 702 | const struct_type: Type = .fromInterned(aggregate.ty); |
| 702 | const clobber = std.mem.sliceTo(extra_bytes, 0); | 703 | switch (aggregate.storage) { |
| 703 | // This equation accounts for the fact that even if we have exactly 4 bytes | 704 | .elems => |elems| for (elems, 0..) |elem, i| { |
| 704 | // for the string, we still use the next u32 for the null terminator. | 705 | switch (elem) { |
| 705 | extra_i += clobber.len / 4 + 1; | 706 | .bool_true => { |
| 706 | 707 | const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 707 | try s.writeAll(", ~{"); | 708 | assert(clobber.len != 0); |
| 708 | try s.writeAll(clobber); | 709 | try s.writeAll(", ~{"); |
| 709 | try s.writeAll("}"); | 710 | try s.writeAll(clobber); |
| 710 | } | 711 | try s.writeAll("}"); |
| 712 | }, | ||
| 713 | .bool_false => continue, | ||
| 714 | else => unreachable, | ||
| 715 | } | ||
| 716 | }, | ||
| 717 | .repeated_elem => |elem| { | ||
| 718 | try s.writeAll(", "); | ||
| 719 | try s.writeAll(switch (elem) { | ||
| 720 | .bool_true => "<all clobbers>", | ||
| 721 | .bool_false => "<no clobbers>", | ||
| 722 | else => unreachable, | ||
| 723 | }); | ||
| 724 | }, | ||
| 725 | .bytes => |bytes| { | ||
| 726 | try s.print(", {x}", .{bytes}); | ||
| 727 | }, | ||
| 711 | } | 728 | } |
| 712 | const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len]; | 729 | const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len]; |
| 713 | try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)}); | 730 | try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)}); |
src/Air/types_resolved.zig+3-2| ... | @@ -416,8 +416,9 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { | ... | @@ -416,8 +416,9 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { |
| 416 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | 416 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; |
| 417 | // Luckily, we only care about the inputs and outputs, so we don't have to do | 417 | // Luckily, we only care about the inputs and outputs, so we don't have to do |
| 418 | // the whole null-terminated string dance. | 418 | // the whole null-terminated string dance. |
| 419 | const outputs: []const Air.Inst.Ref = @ptrCast(air.extra.items[extra.end..][0..extra.data.outputs_len]); | 419 | const outputs_len = extra.data.flags.outputs_len; |
| 420 | const inputs: []const Air.Inst.Ref = @ptrCast(air.extra.items[extra.end + extra.data.outputs_len ..][0..extra.data.inputs_len]); | 420 | const outputs: []const Air.Inst.Ref = @ptrCast(air.extra.items[extra.end..][0..outputs_len]); |
| 421 | const inputs: []const Air.Inst.Ref = @ptrCast(air.extra.items[extra.end + outputs_len ..][0..extra.data.inputs_len]); | ||
| 421 | for (outputs) |output| if (output != .none and !checkRef(output, zcu)) return false; | 422 | for (outputs) |output| if (output != .none and !checkRef(output, zcu)) return false; |
| 422 | for (inputs) |input| if (input != .none and !checkRef(input, zcu)) return false; | 423 | for (inputs) |input| if (input != .none and !checkRef(input, zcu)) return false; |
| 423 | }, | 424 | }, |
src/InternPool.zig+6| ... | @@ -54,6 +54,7 @@ namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.In | ... | @@ -54,6 +54,7 @@ namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.In |
| 54 | memoized_state_main_deps: DepEntry.Index.Optional, | 54 | memoized_state_main_deps: DepEntry.Index.Optional, |
| 55 | memoized_state_panic_deps: DepEntry.Index.Optional, | 55 | memoized_state_panic_deps: DepEntry.Index.Optional, |
| 56 | memoized_state_va_list_deps: DepEntry.Index.Optional, | 56 | memoized_state_va_list_deps: DepEntry.Index.Optional, |
| 57 | memoized_state_assembly_deps: DepEntry.Index.Optional, | ||
| 57 | 58 | ||
| 58 | /// Given a `Depender`, points to an entry in `dep_entries` whose `depender` | 59 | /// Given a `Depender`, points to an entry in `dep_entries` whose `depender` |
| 59 | /// matches. The `next_dependee` field can be used to iterate all such entries | 60 | /// matches. The `next_dependee` field can be used to iterate all such entries |
| ... | @@ -96,6 +97,7 @@ pub const empty: InternPool = .{ | ... | @@ -96,6 +97,7 @@ pub const empty: InternPool = .{ |
| 96 | .memoized_state_main_deps = .none, | 97 | .memoized_state_main_deps = .none, |
| 97 | .memoized_state_panic_deps = .none, | 98 | .memoized_state_panic_deps = .none, |
| 98 | .memoized_state_va_list_deps = .none, | 99 | .memoized_state_va_list_deps = .none, |
| 100 | .memoized_state_assembly_deps = .none, | ||
| 99 | .first_dependency = .empty, | 101 | .first_dependency = .empty, |
| 100 | .dep_entries = .empty, | 102 | .dep_entries = .empty, |
| 101 | .free_dep_entries = .empty, | 103 | .free_dep_entries = .empty, |
| ... | @@ -458,6 +460,8 @@ pub const MemoizedStateStage = enum(u32) { | ... | @@ -458,6 +460,8 @@ pub const MemoizedStateStage = enum(u32) { |
| 458 | panic, | 460 | panic, |
| 459 | /// Specifically `std.builtin.VaList`. See `Zcu.BuiltinDecl.stage`. | 461 | /// Specifically `std.builtin.VaList`. See `Zcu.BuiltinDecl.stage`. |
| 460 | va_list, | 462 | va_list, |
| 463 | /// Everything within `std.builtin.assembly`. See `Zcu.BuiltinDecl.stage`. | ||
| 464 | assembly, | ||
| 461 | }; | 465 | }; |
| 462 | 466 | ||
| 463 | pub const ComptimeUnit = extern struct { | 467 | pub const ComptimeUnit = extern struct { |
| ... | @@ -880,6 +884,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI | ... | @@ -880,6 +884,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI |
| 880 | .main => ip.memoized_state_main_deps.unwrap(), | 884 | .main => ip.memoized_state_main_deps.unwrap(), |
| 881 | .panic => ip.memoized_state_panic_deps.unwrap(), | 885 | .panic => ip.memoized_state_panic_deps.unwrap(), |
| 882 | .va_list => ip.memoized_state_va_list_deps.unwrap(), | 886 | .va_list => ip.memoized_state_va_list_deps.unwrap(), |
| 887 | .assembly => ip.memoized_state_assembly_deps.unwrap(), | ||
| 883 | }, | 888 | }, |
| 884 | } orelse return .{ | 889 | } orelse return .{ |
| 885 | .ip = ip, | 890 | .ip = ip, |
| ... | @@ -915,6 +920,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend | ... | @@ -915,6 +920,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend |
| 915 | .main => &ip.memoized_state_main_deps, | 920 | .main => &ip.memoized_state_main_deps, |
| 916 | .panic => &ip.memoized_state_panic_deps, | 921 | .panic => &ip.memoized_state_panic_deps, |
| 917 | .va_list => &ip.memoized_state_va_list_deps, | 922 | .va_list => &ip.memoized_state_va_list_deps, |
| 923 | .assembly => &ip.memoized_state_assembly_deps, | ||
| 918 | }; | 924 | }; |
| 919 | 925 | ||
| 920 | if (deps.unwrap()) |first| { | 926 | if (deps.unwrap()) |first| { |
src/Sema.zig+17-23| ... | @@ -16413,10 +16413,10 @@ fn zirAsm( | ... | @@ -16413,10 +16413,10 @@ fn zirAsm( |
| 16413 | const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); | 16413 | const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); |
| 16414 | const src = block.nodeOffset(extra.data.src_node); | 16414 | const src = block.nodeOffset(extra.data.src_node); |
| 16415 | const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node }); | 16415 | const ret_ty_src = block.src(.{ .node_offset_asm_ret_ty = extra.data.src_node }); |
| 16416 | const outputs_len: u4 = @truncate(extended.small); | 16416 | const small: Zir.Inst.Asm.Small = @bitCast(extended.small); |
| 16417 | const inputs_len: u5 = @truncate(extended.small >> 4); | 16417 | const outputs_len = small.outputs_len; |
| 16418 | const clobbers_len: u6 = @truncate(extended.small >> 9); | 16418 | const inputs_len = small.inputs_len; |
| 16419 | const is_volatile = @as(u1, @truncate(extended.small >> 15)) != 0; | 16419 | const is_volatile = small.is_volatile; |
| 16420 | const is_global_assembly = sema.func_index == .none; | 16420 | const is_global_assembly = sema.func_index == .none; |
| 16421 | const zir_tags = sema.code.instructions.items(.tag); | 16421 | const zir_tags = sema.code.instructions.items(.tag); |
| 16422 | 16422 | ||
| ... | @@ -16432,7 +16432,7 @@ fn zirAsm( | ... | @@ -16432,7 +16432,7 @@ fn zirAsm( |
| 16432 | if (inputs_len != 0) { | 16432 | if (inputs_len != 0) { |
| 16433 | return sema.fail(block, src, "module-level assembly does not support inputs", .{}); | 16433 | return sema.fail(block, src, "module-level assembly does not support inputs", .{}); |
| 16434 | } | 16434 | } |
| 16435 | if (clobbers_len != 0) { | 16435 | if (extra.data.clobbers != .none) { |
| 16436 | return sema.fail(block, src, "module-level assembly does not support clobbers", .{}); | 16436 | return sema.fail(block, src, "module-level assembly does not support clobbers", .{}); |
| 16437 | } | 16437 | } |
| 16438 | if (is_volatile) { | 16438 | if (is_volatile) { |
| ... | @@ -16506,15 +16506,11 @@ fn zirAsm( | ... | @@ -16506,15 +16506,11 @@ fn zirAsm( |
| 16506 | inputs[arg_i] = .{ .c = constraint, .n = name }; | 16506 | inputs[arg_i] = .{ .c = constraint, .n = name }; |
| 16507 | } | 16507 | } |
| 16508 | 16508 | ||
| 16509 | const clobbers = try sema.arena.alloc([]const u8, clobbers_len); | 16509 | const clobbers = if (extra.data.clobbers == .none) empty: { |
| 16510 | for (clobbers) |*name| { | 16510 | const clobbers_ty = try sema.getBuiltinType(src, .@"assembly.Clobbers"); |
| 16511 | const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_i]); | 16511 | break :empty try sema.structInitEmpty(block, clobbers_ty, src, src); |
| 16512 | name.* = sema.code.nullTerminatedString(name_index); | 16512 | } else try sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen. |
| 16513 | extra_i += 1; | 16513 | const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber }); |
| 16514 | |||
| 16515 | needed_capacity += name.*.len / 4 + 1; | ||
| 16516 | } | ||
| 16517 | |||
| 16518 | needed_capacity += (asm_source.len + 3) / 4; | 16514 | needed_capacity += (asm_source.len + 3) / 4; |
| 16519 | 16515 | ||
| 16520 | const gpa = sema.gpa; | 16516 | const gpa = sema.gpa; |
| ... | @@ -16525,9 +16521,12 @@ fn zirAsm( | ... | @@ -16525,9 +16521,12 @@ fn zirAsm( |
| 16525 | .ty = expr_ty, | 16521 | .ty = expr_ty, |
| 16526 | .payload = sema.addExtraAssumeCapacity(Air.Asm{ | 16522 | .payload = sema.addExtraAssumeCapacity(Air.Asm{ |
| 16527 | .source_len = @intCast(asm_source.len), | 16523 | .source_len = @intCast(asm_source.len), |
| 16528 | .outputs_len = outputs_len, | ||
| 16529 | .inputs_len = @intCast(args.len), | 16524 | .inputs_len = @intCast(args.len), |
| 16530 | .flags = (@as(u32, @intFromBool(is_volatile)) << 31) | @as(u32, @intCast(clobbers.len)), | 16525 | .clobbers = clobbers_val.toIntern(), |
| 16526 | .flags = .{ | ||
| 16527 | .is_volatile = is_volatile, | ||
| 16528 | .outputs_len = outputs_len, | ||
| 16529 | }, | ||
| 16531 | }), | 16530 | }), |
| 16532 | } }, | 16531 | } }, |
| 16533 | }); | 16532 | }); |
| ... | @@ -16549,12 +16548,6 @@ fn zirAsm( | ... | @@ -16549,12 +16548,6 @@ fn zirAsm( |
| 16549 | buffer[input.c.len + 1 + input.n.len] = 0; | 16548 | buffer[input.c.len + 1 + input.n.len] = 0; |
| 16550 | sema.air_extra.items.len += (input.c.len + input.n.len + (2 + 3)) / 4; | 16549 | sema.air_extra.items.len += (input.c.len + input.n.len + (2 + 3)) / 4; |
| 16551 | } | 16550 | } |
| 16552 | for (clobbers) |clobber| { | ||
| 16553 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); | ||
| 16554 | @memcpy(buffer[0..clobber.len], clobber); | ||
| 16555 | buffer[clobber.len] = 0; | ||
| 16556 | sema.air_extra.items.len += clobber.len / 4 + 1; | ||
| 16557 | } | ||
| 16558 | { | 16551 | { |
| 16559 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); | 16552 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); |
| 16560 | @memcpy(buffer[0..asm_source.len], asm_source); | 16553 | @memcpy(buffer[0..asm_source.len], asm_source); |
| ... | @@ -26197,6 +26190,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -26197,6 +26190,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 26197 | .extern_options => try sema.getBuiltinType(src, .ExternOptions), | 26190 | .extern_options => try sema.getBuiltinType(src, .ExternOptions), |
| 26198 | .type_info => try sema.getBuiltinType(src, .Type), | 26191 | .type_info => try sema.getBuiltinType(src, .Type), |
| 26199 | .branch_hint => try sema.getBuiltinType(src, .BranchHint), | 26192 | .branch_hint => try sema.getBuiltinType(src, .BranchHint), |
| 26193 | .clobbers => try sema.getBuiltinType(src, .@"assembly.Clobbers"), | ||
| 26200 | // zig fmt: on | 26194 | // zig fmt: on |
| 26201 | 26195 | ||
| 26202 | // Values are handled here. | 26196 | // Values are handled here. |
| ... | @@ -36546,7 +36540,7 @@ fn payloadToExtraItems(data: anytype) [@typeInfo(@TypeOf(data)).@"struct".fields | ... | @@ -36546,7 +36540,7 @@ fn payloadToExtraItems(data: anytype) [@typeInfo(@TypeOf(data)).@"struct".fields |
| 36546 | inline for (&result, fields) |*val, field| { | 36540 | inline for (&result, fields) |*val, field| { |
| 36547 | val.* = switch (field.type) { | 36541 | val.* = switch (field.type) { |
| 36548 | u32 => @field(data, field.name), | 36542 | u32 => @field(data, field.name), |
| 36549 | i32, Air.CondBr.BranchHints => @bitCast(@field(data, field.name)), | 36543 | i32, Air.CondBr.BranchHints, Air.Asm.Flags => @bitCast(@field(data, field.name)), |
| 36550 | Air.Inst.Ref, InternPool.Index => @intFromEnum(@field(data, field.name)), | 36544 | Air.Inst.Ref, InternPool.Index => @intFromEnum(@field(data, field.name)), |
| 36551 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 36545 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 36552 | }; | 36546 | }; |
src/Zcu.zig+19-7| ... | @@ -460,6 +460,9 @@ pub const BuiltinDecl = enum { | ... | @@ -460,6 +460,9 @@ pub const BuiltinDecl = enum { |
| 460 | 460 | ||
| 461 | VaList, | 461 | VaList, |
| 462 | 462 | ||
| 463 | assembly, | ||
| 464 | @"assembly.Clobbers", | ||
| 465 | |||
| 463 | /// Determines what kind of validation will be done to the decl's value. | 466 | /// Determines what kind of validation will be done to the decl's value. |
| 464 | pub fn kind(decl: BuiltinDecl) enum { type, func, string } { | 467 | pub fn kind(decl: BuiltinDecl) enum { type, func, string } { |
| 465 | return switch (decl) { | 468 | return switch (decl) { |
| ... | @@ -480,6 +483,8 @@ pub const BuiltinDecl = enum { | ... | @@ -480,6 +483,8 @@ pub const BuiltinDecl = enum { |
| 480 | .ExportOptions, | 483 | .ExportOptions, |
| 481 | .ExternOptions, | 484 | .ExternOptions, |
| 482 | .BranchHint, | 485 | .BranchHint, |
| 486 | .assembly, | ||
| 487 | .@"assembly.Clobbers", | ||
| 483 | => .type, | 488 | => .type, |
| 484 | 489 | ||
| 485 | .Type, | 490 | .Type, |
| ... | @@ -540,6 +545,7 @@ pub const BuiltinDecl = enum { | ... | @@ -540,6 +545,7 @@ pub const BuiltinDecl = enum { |
| 540 | /// Resolution of these values is done in three distinct stages: | 545 | /// Resolution of these values is done in three distinct stages: |
| 541 | /// * Resolution of `std.builtin.Panic` and everything under it | 546 | /// * Resolution of `std.builtin.Panic` and everything under it |
| 542 | /// * Resolution of `VaList` | 547 | /// * Resolution of `VaList` |
| 548 | /// * Resolution of `assembly` | ||
| 543 | /// * Everything else | 549 | /// * Everything else |
| 544 | /// | 550 | /// |
| 545 | /// Panics are separated because they are provided by the user, so must be able to use | 551 | /// Panics are separated because they are provided by the user, so must be able to use |
| ... | @@ -548,14 +554,20 @@ pub const BuiltinDecl = enum { | ... | @@ -548,14 +554,20 @@ pub const BuiltinDecl = enum { |
| 548 | /// `VaList` is separate because its value depends on the target, so it needs some reflection | 554 | /// `VaList` is separate because its value depends on the target, so it needs some reflection |
| 549 | /// machinery to work; additionally, it is `@compileError` on some targets, so must be referenced | 555 | /// machinery to work; additionally, it is `@compileError` on some targets, so must be referenced |
| 550 | /// by itself. | 556 | /// by itself. |
| 557 | /// | ||
| 558 | /// `assembly` is separate because its value depends on the target. | ||
| 551 | pub fn stage(decl: BuiltinDecl) InternPool.MemoizedStateStage { | 559 | pub fn stage(decl: BuiltinDecl) InternPool.MemoizedStateStage { |
| 552 | if (decl == .VaList) return .va_list; | 560 | return switch (decl) { |
| 553 | 561 | .VaList => .va_list, | |
| 554 | if (@intFromEnum(decl) <= @intFromEnum(BuiltinDecl.@"Type.Declaration")) { | 562 | .assembly, .@"assembly.Clobbers" => .assembly, |
| 555 | return .main; | 563 | else => { |
| 556 | } else { | 564 | if (@intFromEnum(decl) <= @intFromEnum(BuiltinDecl.@"Type.Declaration")) { |
| 557 | return .panic; | 565 | return .main; |
| 558 | } | 566 | } else { |
| 567 | return .panic; | ||
| 568 | } | ||
| 569 | }, | ||
| 570 | }; | ||
| 559 | } | 571 | } |
| 560 | 572 | ||
| 561 | /// Based on the tag name, determines how to access this decl; either as a direct child of the | 573 | /// Based on the tag name, determines how to access this decl; either as a direct child of the |
src/Zcu/PerThread.zig+1| ... | @@ -635,6 +635,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized | ... | @@ -635,6 +635,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 635 | .main => .Type, | 635 | .main => .Type, |
| 636 | .panic => .panic, | 636 | .panic => .panic, |
| 637 | .va_list => .VaList, | 637 | .va_list => .VaList, |
| 638 | .assembly => .assembly, | ||
| 638 | }; | 639 | }; |
| 639 | if (zcu.builtin_decl_values.get(to_check) != .none) return; | 640 | if (zcu.builtin_decl_values.get(to_check) != .none) return; |
| 640 | } | 641 | } |
src/arch/riscv64/CodeGen.zig+28-16| ... | @@ -6047,10 +6047,10 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6047,10 +6047,10 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void { |
| 6047 | fn airAsm(func: *Func, inst: Air.Inst.Index) !void { | 6047 | fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 6048 | const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 6048 | const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6049 | const extra = func.air.extraData(Air.Asm, ty_pl.payload); | 6049 | const extra = func.air.extraData(Air.Asm, ty_pl.payload); |
| 6050 | const clobbers_len: u31 = @truncate(extra.data.flags); | 6050 | const outputs_len = extra.data.flags.outputs_len; |
| 6051 | var extra_i: usize = extra.end; | 6051 | var extra_i: usize = extra.end; |
| 6052 | const outputs: []const Air.Inst.Ref = | 6052 | const outputs: []const Air.Inst.Ref = |
| 6053 | @ptrCast(func.air.extra.items[extra_i..][0..extra.data.outputs_len]); | 6053 | @ptrCast(func.air.extra.items[extra_i..][0..outputs_len]); |
| 6054 | extra_i += outputs.len; | 6054 | extra_i += outputs.len; |
| 6055 | const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra.items[extra_i..][0..extra.data.inputs_len]); | 6055 | const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra.items[extra_i..][0..extra.data.inputs_len]); |
| 6056 | extra_i += inputs.len; | 6056 | extra_i += inputs.len; |
| ... | @@ -6161,21 +6161,33 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6161,21 +6161,33 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 6161 | args.appendAssumeCapacity(arg_mcv); | 6161 | args.appendAssumeCapacity(arg_mcv); |
| 6162 | } | 6162 | } |
| 6163 | 6163 | ||
| 6164 | { | 6164 | const zcu = func.pt.zcu; |
| 6165 | var clobber_i: u32 = 0; | 6165 | const ip = &zcu.intern_pool; |
| 6166 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | 6166 | const aggregate = ip.indexToKey(extra.data.clobbers).aggregate; |
| 6167 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(func.air.extra.items[extra_i..]), 0); | 6167 | const struct_type: Type = .fromInterned(aggregate.ty); |
| 6168 | // This equation accounts for the fact that even if we have exactly 4 bytes | 6168 | switch (aggregate.storage) { |
| 6169 | // for the string, we still use the next u32 for the null terminator. | 6169 | .elems => |elems| for (elems, 0..) |elem, i| { |
| 6170 | extra_i += clobber.len / 4 + 1; | 6170 | switch (elem) { |
| 6171 | 6171 | .bool_true => { | |
| 6172 | if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) { | 6172 | const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; |
| 6173 | // nothing really to do | 6173 | assert(clobber.len != 0); |
| 6174 | } else { | 6174 | if (std.mem.eql(u8, clobber, "memory")) { |
| 6175 | try func.register_manager.getReg(parseRegName(clobber) orelse | 6175 | // nothing really to do |
| 6176 | return func.fail("invalid clobber: '{s}'", .{clobber}), null); | 6176 | } else { |
| 6177 | try func.register_manager.getReg(parseRegName(clobber) orelse | ||
| 6178 | return func.fail("invalid clobber: '{s}'", .{clobber}), null); | ||
| 6179 | } | ||
| 6180 | }, | ||
| 6181 | .bool_false => continue, | ||
| 6182 | else => unreachable, | ||
| 6177 | } | 6183 | } |
| 6178 | } | 6184 | }, |
| 6185 | .repeated_elem => |elem| switch (elem) { | ||
| 6186 | .bool_true => @panic("TODO"), | ||
| 6187 | .bool_false => {}, | ||
| 6188 | else => unreachable, | ||
| 6189 | }, | ||
| 6190 | .bytes => @panic("TODO"), | ||
| 6179 | } | 6191 | } |
| 6180 | 6192 | ||
| 6181 | const Label = struct { | 6193 | const Label = struct { |
src/arch/sparc64/CodeGen.zig+5-14| ... | @@ -873,10 +873,10 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -873,10 +873,10 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 873 | fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | 873 | fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 874 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 874 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 875 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); | 875 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 876 | const is_volatile = (extra.data.flags & 0x80000000) != 0; | 876 | const is_volatile = extra.data.flags.is_volatile; |
| 877 | const clobbers_len: u31 = @truncate(extra.data.flags); | 877 | const outputs_len = extra.data.flags.outputs_len; |
| 878 | var extra_i: usize = extra.end; | 878 | var extra_i: usize = extra.end; |
| 879 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i .. extra_i + extra.data.outputs_len]); | 879 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i .. extra_i + outputs_len]); |
| 880 | extra_i += outputs.len; | 880 | extra_i += outputs.len; |
| 881 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i .. extra_i + extra.data.inputs_len]); | 881 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i .. extra_i + extra.data.inputs_len]); |
| 882 | extra_i += inputs.len; | 882 | extra_i += inputs.len; |
| ... | @@ -921,17 +921,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -921,17 +921,8 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 921 | try self.genSetReg(self.typeOf(input), reg, arg_mcv); | 921 | try self.genSetReg(self.typeOf(input), reg, arg_mcv); |
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | { | 924 | // TODO honor the clobbers |
| 925 | var clobber_i: u32 = 0; | 925 | _ = extra.data.clobbers; |
| 926 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | ||
| 927 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra.items[extra_i..]), 0); | ||
| 928 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 929 | // for the string, we still use the next u32 for the null terminator. | ||
| 930 | extra_i += clobber.len / 4 + 1; | ||
| 931 | |||
| 932 | // TODO honor these | ||
| 933 | } | ||
| 934 | } | ||
| 935 | 926 | ||
| 936 | const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len]; | 927 | const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len]; |
| 937 | 928 |
src/arch/x86_64/CodeGen.zig+38-26| ... | @@ -179788,9 +179788,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -179788,9 +179788,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 179788 | const zcu = pt.zcu; | 179788 | const zcu = pt.zcu; |
| 179789 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 179789 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 179790 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); | 179790 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 179791 | const clobbers_len: u31 = @truncate(extra.data.flags); | 179791 | const outputs_len = extra.data.flags.outputs_len; |
| 179792 | var extra_i: usize = extra.end; | 179792 | var extra_i: usize = extra.end; |
| 179793 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.outputs_len]); | 179793 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..outputs_len]); |
| 179794 | extra_i += outputs.len; | 179794 | extra_i += outputs.len; |
| 179795 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); | 179795 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); |
| 179796 | extra_i += inputs.len; | 179796 | extra_i += inputs.len; |
| ... | @@ -179981,30 +179981,42 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -179981,30 +179981,42 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 179981 | args.appendAssumeCapacity(arg_mcv); | 179981 | args.appendAssumeCapacity(arg_mcv); |
| 179982 | } | 179982 | } |
| 179983 | 179983 | ||
| 179984 | { | 179984 | const ip = &zcu.intern_pool; |
| 179985 | var clobber_i: u32 = 0; | 179985 | const aggregate = ip.indexToKey(extra.data.clobbers).aggregate; |
| 179986 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | 179986 | const struct_type: Type = .fromInterned(aggregate.ty); |
| 179987 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra.items[extra_i..]), 0); | 179987 | switch (aggregate.storage) { |
| 179988 | // This equation accounts for the fact that even if we have exactly 4 bytes | 179988 | .elems => |elems| for (elems, 0..) |elem, i| switch (elem) { |
| 179989 | // for the string, we still use the next u32 for the null terminator. | 179989 | .bool_true => { |
| 179990 | extra_i += clobber.len / 4 + 1; | 179990 | const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; |
| 179991 | 179991 | assert(clobber.len != 0); | |
| 179992 | if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory") or | 179992 | |
| 179993 | std.mem.eql(u8, clobber, "fpsr") or std.mem.eql(u8, clobber, "fpcr") or | 179993 | if (std.mem.eql(u8, clobber, "memory") or |
| 179994 | std.mem.eql(u8, clobber, "mxcsr") or std.mem.eql(u8, clobber, "dirflag")) | 179994 | std.mem.eql(u8, clobber, "fpsr") or |
| 179995 | { | 179995 | std.mem.eql(u8, clobber, "fpcr") or |
| 179996 | // ok, sure | 179996 | std.mem.eql(u8, clobber, "mxcsr") or |
| 179997 | } else if (std.mem.eql(u8, clobber, "cc") or | 179997 | std.mem.eql(u8, clobber, "dirflag")) |
| 179998 | std.mem.eql(u8, clobber, "flags") or | 179998 | { |
| 179999 | std.mem.eql(u8, clobber, "eflags") or | 179999 | // ok, sure |
| 180000 | std.mem.eql(u8, clobber, "rflags")) | 180000 | } else if (std.mem.eql(u8, clobber, "cc") or |
| 180001 | { | 180001 | std.mem.eql(u8, clobber, "flags") or |
| 180002 | try self.spillEflagsIfOccupied(); | 180002 | std.mem.eql(u8, clobber, "eflags") or |
| 180003 | } else { | 180003 | std.mem.eql(u8, clobber, "rflags")) |
| 180004 | try self.register_manager.getReg(parseRegName(clobber) orelse | 180004 | { |
| 180005 | return self.fail("invalid clobber: '{s}'", .{clobber}), null); | 180005 | try self.spillEflagsIfOccupied(); |
| 180006 | } | 180006 | } else { |
| 180007 | } | 180007 | try self.register_manager.getReg(parseRegName(clobber) orelse |
| 180008 | return self.fail("invalid clobber: '{s}'", .{clobber}), null); | ||
| 180009 | } | ||
| 180010 | }, | ||
| 180011 | .bool_false => continue, | ||
| 180012 | else => unreachable, | ||
| 180013 | }, | ||
| 180014 | .repeated_elem => |elem| switch (elem) { | ||
| 180015 | .bool_true => @panic("TODO"), | ||
| 180016 | .bool_false => {}, | ||
| 180017 | else => unreachable, | ||
| 180018 | }, | ||
| 180019 | .bytes => @panic("TODO"), | ||
| 180008 | } | 180020 | } |
| 180009 | 180021 | ||
| 180010 | const Label = struct { | 180022 | const Label = struct { |
src/codegen/c.zig+24-19| ... | @@ -5545,11 +5545,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5545,11 +5545,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5545 | const zcu = pt.zcu; | 5545 | const zcu = pt.zcu; |
| 5546 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5546 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5547 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); | 5547 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); |
| 5548 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | 5548 | const is_volatile = extra.data.flags.is_volatile; |
| 5549 | const clobbers_len: u31 = @truncate(extra.data.flags); | 5549 | const outputs_len = extra.data.flags.outputs_len; |
| 5550 | const gpa = f.object.dg.gpa; | 5550 | const gpa = f.object.dg.gpa; |
| 5551 | var extra_i: usize = extra.end; | 5551 | var extra_i: usize = extra.end; |
| 5552 | const outputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.outputs_len]); | 5552 | const outputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..outputs_len]); |
| 5553 | extra_i += outputs.len; | 5553 | extra_i += outputs.len; |
| 5554 | const inputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.inputs_len]); | 5554 | const inputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.inputs_len]); |
| 5555 | extra_i += inputs.len; | 5555 | extra_i += inputs.len; |
| ... | @@ -5645,12 +5645,6 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5645,12 +5645,6 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5645 | try f.object.newline(); | 5645 | try f.object.newline(); |
| 5646 | } | 5646 | } |
| 5647 | } | 5647 | } |
| 5648 | for (0..clobbers_len) |_| { | ||
| 5649 | const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0); | ||
| 5650 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 5651 | // for the string, we still use the next u32 for the null terminator. | ||
| 5652 | extra_i += clobber.len / 4 + 1; | ||
| 5653 | } | ||
| 5654 | 5648 | ||
| 5655 | { | 5649 | { |
| 5656 | const asm_source = mem.sliceAsBytes(f.air.extra.items[extra_i..])[0..extra.data.source_len]; | 5650 | const asm_source = mem.sliceAsBytes(f.air.extra.items[extra_i..])[0..extra.data.source_len]; |
| ... | @@ -5757,17 +5751,28 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5757,17 +5751,28 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5757 | try w.writeByte(')'); | 5751 | try w.writeByte(')'); |
| 5758 | } | 5752 | } |
| 5759 | try w.writeByte(':'); | 5753 | try w.writeByte(':'); |
| 5760 | for (0..clobbers_len) |clobber_i| { | 5754 | const ip = &zcu.intern_pool; |
| 5761 | const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0); | 5755 | const aggregate = ip.indexToKey(extra.data.clobbers).aggregate; |
| 5762 | // This equation accounts for the fact that even if we have exactly 4 bytes | 5756 | const struct_type: Type = .fromInterned(aggregate.ty); |
| 5763 | // for the string, we still use the next u32 for the null terminator. | 5757 | switch (aggregate.storage) { |
| 5764 | extra_i += clobber.len / 4 + 1; | 5758 | .elems => |elems| for (elems, 0..) |elem, i| switch (elem) { |
| 5765 | 5759 | .bool_true => { | |
| 5766 | if (clobber.len == 0) continue; | 5760 | const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; |
| 5767 | 5761 | assert(name.len != 0); | |
| 5768 | if (clobber_i > 0) try w.writeByte(','); | 5762 | try w.print(" {f}", .{fmtStringLiteral(name, null)}); |
| 5769 | try w.print(" {f}", .{fmtStringLiteral(clobber, null)}); | 5763 | (try w.writableArray(1))[0] = ','; |
| 5764 | }, | ||
| 5765 | .bool_false => continue, | ||
| 5766 | else => unreachable, | ||
| 5767 | }, | ||
| 5768 | .repeated_elem => |elem| switch (elem) { | ||
| 5769 | .bool_true => @panic("TODO"), | ||
| 5770 | .bool_false => {}, | ||
| 5771 | else => unreachable, | ||
| 5772 | }, | ||
| 5773 | .bytes => @panic("TODO"), | ||
| 5770 | } | 5774 | } |
| 5775 | w.undo(1); // erase the last comma | ||
| 5771 | try w.writeAll(");"); | 5776 | try w.writeAll(");"); |
| 5772 | try f.object.newline(); | 5777 | try f.object.newline(); |
| 5773 | 5778 |
src/codegen/llvm.zig+47-29| ... | @@ -7241,19 +7241,20 @@ pub const FuncGen = struct { | ... | @@ -7241,19 +7241,20 @@ pub const FuncGen = struct { |
| 7241 | const o = self.ng.object; | 7241 | const o = self.ng.object; |
| 7242 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 7242 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 7243 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); | 7243 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 7244 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | 7244 | const is_volatile = extra.data.flags.is_volatile; |
| 7245 | const clobbers_len: u31 = @truncate(extra.data.flags); | 7245 | const outputs_len = extra.data.flags.outputs_len; |
| 7246 | const gpa = self.gpa; | ||
| 7246 | var extra_i: usize = extra.end; | 7247 | var extra_i: usize = extra.end; |
| 7247 | 7248 | ||
| 7248 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.outputs_len]); | 7249 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..outputs_len]); |
| 7249 | extra_i += outputs.len; | 7250 | extra_i += outputs.len; |
| 7250 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); | 7251 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); |
| 7251 | extra_i += inputs.len; | 7252 | extra_i += inputs.len; |
| 7252 | 7253 | ||
| 7253 | var llvm_constraints: std.ArrayListUnmanaged(u8) = .empty; | 7254 | var llvm_constraints: std.ArrayListUnmanaged(u8) = .empty; |
| 7254 | defer llvm_constraints.deinit(self.gpa); | 7255 | defer llvm_constraints.deinit(gpa); |
| 7255 | 7256 | ||
| 7256 | var arena_allocator = std.heap.ArenaAllocator.init(self.gpa); | 7257 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| 7257 | defer arena_allocator.deinit(); | 7258 | defer arena_allocator.deinit(); |
| 7258 | const arena = arena_allocator.allocator(); | 7259 | const arena = arena_allocator.allocator(); |
| 7259 | 7260 | ||
| ... | @@ -7290,7 +7291,7 @@ pub const FuncGen = struct { | ... | @@ -7290,7 +7291,7 @@ pub const FuncGen = struct { |
| 7290 | // for the string, we still use the next u32 for the null terminator. | 7291 | // for the string, we still use the next u32 for the null terminator. |
| 7291 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; | 7292 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; |
| 7292 | 7293 | ||
| 7293 | try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 3); | 7294 | try llvm_constraints.ensureUnusedCapacity(gpa, constraint.len + 3); |
| 7294 | if (total_i != 0) { | 7295 | if (total_i != 0) { |
| 7295 | llvm_constraints.appendAssumeCapacity(','); | 7296 | llvm_constraints.appendAssumeCapacity(','); |
| 7296 | } | 7297 | } |
| ... | @@ -7399,7 +7400,7 @@ pub const FuncGen = struct { | ... | @@ -7399,7 +7400,7 @@ pub const FuncGen = struct { |
| 7399 | } | 7400 | } |
| 7400 | } | 7401 | } |
| 7401 | 7402 | ||
| 7402 | try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1); | 7403 | try llvm_constraints.ensureUnusedCapacity(gpa, constraint.len + 1); |
| 7403 | if (total_i != 0) { | 7404 | if (total_i != 0) { |
| 7404 | llvm_constraints.appendAssumeCapacity(','); | 7405 | llvm_constraints.appendAssumeCapacity(','); |
| 7405 | } | 7406 | } |
| ... | @@ -7456,7 +7457,7 @@ pub const FuncGen = struct { | ... | @@ -7456,7 +7457,7 @@ pub const FuncGen = struct { |
| 7456 | llvm_param_types[llvm_param_i] = llvm_elem_ty; | 7457 | llvm_param_types[llvm_param_i] = llvm_elem_ty; |
| 7457 | } | 7458 | } |
| 7458 | 7459 | ||
| 7459 | try llvm_constraints.print(self.gpa, ",{d}", .{output_index}); | 7460 | try llvm_constraints.print(gpa, ",{d}", .{output_index}); |
| 7460 | 7461 | ||
| 7461 | // In the case of indirect inputs, LLVM requires the callsite to have | 7462 | // In the case of indirect inputs, LLVM requires the callsite to have |
| 7462 | // an elementtype(<ty>) attribute. | 7463 | // an elementtype(<ty>) attribute. |
| ... | @@ -7466,24 +7467,41 @@ pub const FuncGen = struct { | ... | @@ -7466,24 +7467,41 @@ pub const FuncGen = struct { |
| 7466 | total_i += 1; | 7467 | total_i += 1; |
| 7467 | } | 7468 | } |
| 7468 | 7469 | ||
| 7469 | { | 7470 | const ip = &zcu.intern_pool; |
| 7470 | var clobber_i: u32 = 0; | 7471 | const aggregate = ip.indexToKey(extra.data.clobbers).aggregate; |
| 7471 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | 7472 | const struct_type: Type = .fromInterned(aggregate.ty); |
| 7472 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra.items[extra_i..]), 0); | 7473 | switch (aggregate.storage) { |
| 7473 | // This equation accounts for the fact that even if we have exactly 4 bytes | 7474 | .elems => |elems| for (elems, 0..) |elem, i| { |
| 7474 | // for the string, we still use the next u32 for the null terminator. | 7475 | switch (elem) { |
| 7475 | extra_i += clobber.len / 4 + 1; | 7476 | .bool_true => { |
| 7476 | 7477 | const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; | |
| 7477 | try llvm_constraints.ensureUnusedCapacity(self.gpa, clobber.len + 4); | 7478 | try llvm_constraints.ensureUnusedCapacity(gpa, name.len + 4); |
| 7478 | if (total_i != 0) { | 7479 | if (total_i != 0) llvm_constraints.appendAssumeCapacity(','); |
| 7479 | llvm_constraints.appendAssumeCapacity(','); | 7480 | llvm_constraints.appendSliceAssumeCapacity("~{"); |
| 7481 | llvm_constraints.appendSliceAssumeCapacity(name); | ||
| 7482 | llvm_constraints.appendSliceAssumeCapacity("}"); | ||
| 7483 | |||
| 7484 | total_i += 1; | ||
| 7485 | }, | ||
| 7486 | .bool_false => continue, | ||
| 7487 | else => unreachable, | ||
| 7480 | } | 7488 | } |
| 7481 | llvm_constraints.appendSliceAssumeCapacity("~{"); | 7489 | }, |
| 7482 | llvm_constraints.appendSliceAssumeCapacity(clobber); | 7490 | .repeated_elem => |elem| switch (elem) { |
| 7483 | llvm_constraints.appendSliceAssumeCapacity("}"); | 7491 | .bool_true => for (0..struct_type.structFieldCount(zcu)) |i| { |
| 7492 | const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; | ||
| 7493 | try llvm_constraints.ensureUnusedCapacity(gpa, name.len + 4); | ||
| 7494 | if (total_i != 0) llvm_constraints.appendAssumeCapacity(','); | ||
| 7495 | llvm_constraints.appendSliceAssumeCapacity("~{"); | ||
| 7496 | llvm_constraints.appendSliceAssumeCapacity(name); | ||
| 7497 | llvm_constraints.appendSliceAssumeCapacity("}"); | ||
| 7484 | 7498 | ||
| 7485 | total_i += 1; | 7499 | total_i += 1; |
| 7486 | } | 7500 | }, |
| 7501 | .bool_false => {}, | ||
| 7502 | else => unreachable, | ||
| 7503 | }, | ||
| 7504 | .bytes => @panic("TODO"), | ||
| 7487 | } | 7505 | } |
| 7488 | 7506 | ||
| 7489 | // We have finished scanning through all inputs/outputs, so the number of | 7507 | // We have finished scanning through all inputs/outputs, so the number of |
| ... | @@ -7497,13 +7515,13 @@ pub const FuncGen = struct { | ... | @@ -7497,13 +7515,13 @@ pub const FuncGen = struct { |
| 7497 | // to be buggy and regress often. | 7515 | // to be buggy and regress often. |
| 7498 | switch (target.cpu.arch) { | 7516 | switch (target.cpu.arch) { |
| 7499 | .x86_64, .x86 => { | 7517 | .x86_64, .x86 => { |
| 7500 | if (total_i != 0) try llvm_constraints.append(self.gpa, ','); | 7518 | if (total_i != 0) try llvm_constraints.append(gpa, ','); |
| 7501 | try llvm_constraints.appendSlice(self.gpa, "~{dirflag},~{fpsr},~{flags}"); | 7519 | try llvm_constraints.appendSlice(gpa, "~{dirflag},~{fpsr},~{flags}"); |
| 7502 | total_i += 3; | 7520 | total_i += 3; |
| 7503 | }, | 7521 | }, |
| 7504 | .mips, .mipsel, .mips64, .mips64el => { | 7522 | .mips, .mipsel, .mips64, .mips64el => { |
| 7505 | if (total_i != 0) try llvm_constraints.append(self.gpa, ','); | 7523 | if (total_i != 0) try llvm_constraints.append(gpa, ','); |
| 7506 | try llvm_constraints.appendSlice(self.gpa, "~{$1}"); | 7524 | try llvm_constraints.appendSlice(gpa, "~{$1}"); |
| 7507 | total_i += 1; | 7525 | total_i += 1; |
| 7508 | }, | 7526 | }, |
| 7509 | else => {}, | 7527 | else => {}, |
| ... | @@ -7512,7 +7530,7 @@ pub const FuncGen = struct { | ... | @@ -7512,7 +7530,7 @@ pub const FuncGen = struct { |
| 7512 | const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len]; | 7530 | const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len]; |
| 7513 | 7531 | ||
| 7514 | // hackety hacks until stage2 has proper inline asm in the frontend. | 7532 | // hackety hacks until stage2 has proper inline asm in the frontend. |
| 7515 | var rendered_template = std.ArrayList(u8).init(self.gpa); | 7533 | var rendered_template = std.ArrayList(u8).init(gpa); |
| 7516 | defer rendered_template.deinit(); | 7534 | defer rendered_template.deinit(); |
| 7517 | 7535 | ||
| 7518 | const State = enum { start, percent, input, modifier }; | 7536 | const State = enum { start, percent, input, modifier }; |
src/codegen/spirv.zig+6-12| ... | @@ -6387,13 +6387,13 @@ const NavGen = struct { | ... | @@ -6387,13 +6387,13 @@ const NavGen = struct { |
| 6387 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 6387 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 6388 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); | 6388 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 6389 | 6389 | ||
| 6390 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | 6390 | const is_volatile = extra.data.flags.is_volatile; |
| 6391 | const clobbers_len: u31 = @truncate(extra.data.flags); | 6391 | const outputs_len = extra.data.flags.outputs_len; |
| 6392 | 6392 | ||
| 6393 | if (!is_volatile and self.liveness.isUnused(inst)) return null; | 6393 | if (!is_volatile and self.liveness.isUnused(inst)) return null; |
| 6394 | 6394 | ||
| 6395 | var extra_i: usize = extra.end; | 6395 | var extra_i: usize = extra.end; |
| 6396 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.outputs_len]); | 6396 | const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..outputs_len]); |
| 6397 | extra_i += outputs.len; | 6397 | extra_i += outputs.len; |
| 6398 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); | 6398 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]); |
| 6399 | extra_i += inputs.len; | 6399 | extra_i += inputs.len; |
| ... | @@ -6402,7 +6402,7 @@ const NavGen = struct { | ... | @@ -6402,7 +6402,7 @@ const NavGen = struct { |
| 6402 | return self.todo("implement inline asm with more than 1 output", .{}); | 6402 | return self.todo("implement inline asm with more than 1 output", .{}); |
| 6403 | } | 6403 | } |
| 6404 | 6404 | ||
| 6405 | var as = SpvAssembler{ | 6405 | var as: SpvAssembler = .{ |
| 6406 | .gpa = self.gpa, | 6406 | .gpa = self.gpa, |
| 6407 | .spv = self.spv, | 6407 | .spv = self.spv, |
| 6408 | .func = &self.func, | 6408 | .func = &self.func, |
| ... | @@ -6486,14 +6486,8 @@ const NavGen = struct { | ... | @@ -6486,14 +6486,8 @@ const NavGen = struct { |
| 6486 | } | 6486 | } |
| 6487 | } | 6487 | } |
| 6488 | 6488 | ||
| 6489 | { | 6489 | // TODO: do something with clobbers |
| 6490 | var clobber_i: u32 = 0; | 6490 | _ = extra.data.clobbers; |
| 6491 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | ||
| 6492 | const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra.items[extra_i..]), 0); | ||
| 6493 | extra_i += clobber.len / 4 + 1; | ||
| 6494 | // TODO: Record clobber and use it somewhere. | ||
| 6495 | } | ||
| 6496 | } | ||
| 6497 | 6491 | ||
| 6498 | const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len]; | 6492 | const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len]; |
| 6499 | 6493 |