Unified · Split
| @@ -86,10 +86,19 @@ modcode(globals: ref Decl) · 85 unmodified lines | |||
| 86 | print("#include \"%s.h\"\n", buf); | 86 | print("#include \"%s.h\"\n", buf); |
| 87 | } | 87 | } |
| 88 | else{ | 88 | else{ |
| 89 | print("#include <lib9.h>\n"); | 89 | print("#include <memory.h>\n"); |
| 90 | print("#include <isa.h>\n"); | 90 | print("#include <disvm.h>\n"); |
| 91 | print("#include <interp.h>\n"); | 91 | print("#include <builtin_module.h>\n"); |
| 92 | print("#include \"%smod.h\"\n", emitcode); | 92 | print("#include \"%smod.h\"\n", emitcode); |
| 93 | print("using disvm::vm_t;\n"); | ||
| 94 | print("using disvm::runtime::type_descriptor_t;\n"); | ||
| 95 | print("using disvm::runtime::vm_registers_t;\n"); | ||
| 96 | print("using disvm::runtime::vm_frame_base_alloc_t;\n"); | ||
| 97 | print("using disvm::runtime::byte_t;\n"); | ||
| 98 | print("using disvm::runtime::word_t;\n"); | ||
| 99 | print("using disvm::runtime::big_t;\n"); | ||
| 100 | print("using disvm::runtime::real_t;\n"); | ||
| 101 | print("using disvm::runtime::pointer_t;\n"); | ||
| 93 | } | 102 | } |
| 94 | print("\n"); | 103 | print("\n"); |
| 95 | 104 | ||
| @@ -106,7 +115,7 @@ modcode(globals: ref Decl) · 10 unmodified lines | |||
| 106 | for(id := d.ty.ids; id != nil; id = id.next){ | 115 | for(id := d.ty.ids; id != nil; id = id.next){ |
| 107 | if(id.store == Dtype && id.ty.kind == Tadt){ | 116 | if(id.store == Dtype && id.ty.kind == Tadt){ |
| 108 | id.ty = usetype(id.ty); | 117 | id.ty = usetype(id.ty); |
| 109 | print("Type*\tT_%s;\n", id.sym.name); | 118 | print("std::shared_ptr<const type_descriptor_t> T_%s;\n", id.sym.name); |
| 110 | } | 119 | } |
| 111 | } | 120 | } |
| 112 | 121 | ||
| @@ -116,7 +125,7 @@ modcode(globals: ref Decl) · 3 unmodified lines | |||
| 116 | if(emitdyn){ | 125 | if(emitdyn){ |
| 117 | for(id = d.ty.ids; id != nil; id = id.next) | 126 | for(id = d.ty.ids; id != nil; id = id.next) |
| 118 | if(id.store == Dtype && id.ty.kind == Tadt) | 127 | if(id.store == Dtype && id.ty.kind == Tadt) |
| 119 | print("uchar %s_map[] = %s_%s_map;\n", | 128 | print("byte_t %s_map[] = %s_%s_map;\n", |
| 120 | id.sym.name, emitcode, id.sym.name); | 129 | id.sym.name, emitcode, id.sym.name); |
| 121 | } | 130 | } |
| 122 | 131 | ||
| @@ -126,8 +135,10 @@ modcode(globals: ref Decl) · 3 unmodified lines | |||
| 126 | if(emitdyn){ | 135 | if(emitdyn){ |
| 127 | for(id = d.ty.ids; id != nil; id = id.next) | 136 | for(id = d.ty.ids; id != nil; id = id.next) |
| 128 | if(id.store == Dtype && id.ty.kind == Tadt){ | 137 | if(id.store == Dtype && id.ty.kind == Tadt){ |
| 129 | print("\n%s_%s*\n%salloc%s(void)\n{\n\tHeap *h;\n\n\th = heap(T_%s);\n\treturn H2D(%s_%s*, h);\n}\n", emitcode, id.sym.name, emitcode, id.sym.name, id.sym.name, emitcode, id.sym.name); | 138 | print("\n%s_%s*\n%salloc%s(void)\n{\n vm_alloc_t *a = vm_alloc_t::allocate(T_%s);\n return ::new(a->get_allocation())%s_%s{};\n}\n", |
| 130 | print("\nvoid\n%sfree%s(Heap *h, int swept)\n{\n\t%s_%s *d;\n\n\td = H2D(%s_%s*, h);\n\tfreeheap(h, swept);\n}\n", emitcode, id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name); | 139 | emitcode, id.sym.name, emitcode, id.sym.name, id.sym.name, emitcode, id.sym.name); |
| 140 | print("\nvoid\n%sfree%s(vm_alloc_t *a)\n{\n // Customized deallocation\n //%s_%s *t = a->get_allocation<%s_%s>();\n //t->~%s_%s();\n\n // Default deallocation\n disvm::runtime::dec_ref_count_and_free(a);\n}\n", | ||
| 141 | emitcode, id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name); | ||
| 131 | } | 142 | } |
| 132 | } | 143 | } |
| 133 | 144 | ||
| @@ -138,16 +149,16 @@ modcode(globals: ref Decl) · 4 unmodified lines | |||
| 138 | print("\nvoid\n%sinit(void)\n{\n", emitcode); | 149 | print("\nvoid\n%sinit(void)\n{\n", emitcode); |
| 139 | else{ | 150 | else{ |
| 140 | print("\nvoid\n%smodinit(void)\n{\n", emitcode); | 151 | print("\nvoid\n%smodinit(void)\n{\n", emitcode); |
| 141 | print("\tbuiltinmod(\"$%s\", %smodtab, %smodlen);\n", emitcode, emitcode, emitcode); | 152 | print(" disvm::runtime::builtin::register_module_exports(%s_PATH, %smodtab, %smodlen);\n", emitcode, emitcode, emitcode); |
| 142 | } | 153 | } |
| 143 | for(id = d.ty.ids; id != nil; id = id.next) | 154 | for(id = d.ty.ids; id != nil; id = id.next) |
| 144 | if(id.store == Dtype && id.ty.kind == Tadt){ | 155 | if(id.store == Dtype && id.ty.kind == Tadt){ |
| 145 | if(emitdyn) | 156 | if(emitdyn) |
| 146 | print("\tT_%s = dtype(%sfree%s, %s_%s_size, %s_map, sizeof(%s_map));\n", | 157 | print(" T_%s = type_descriptor_t::create(%s_%s_size, sizeof(%s_map), %s_map);\n", |
| 147 | id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name, id.sym.name, id.sym.name); | 158 | id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name); |
| 148 | else | 159 | else |
| 149 | print("\tT_%s = dtype(freeheap, sizeof(%s), %smap, sizeof(%smap));\n", | 160 | print(" T_%s = type_descriptor_t::create(sizeof(%s_%s), sizeof(%s_%s_map), %s_%s_map);\n", |
| 150 | id.sym.name, id.sym.name, id.sym.name, id.sym.name); | 161 | id.sym.name, id.dot.sym.name, id.sym.name, id.dot.sym.name, id.sym.name, id.dot.sym.name, id.sym.name); |
| 151 | } | 162 | } |
| 152 | print("}\n"); | 163 | print("}\n"); |
| 153 | 164 | ||
| @@ -155,24 +166,20 @@ modcode(globals: ref Decl) · 1 unmodified line | |||
| 155 | # end function | 166 | # end function |
| 156 | # | 167 | # |
| 157 | if(emitdyn){ | 168 | if(emitdyn){ |
| 158 | print("\nvoid\n%send(void)\n{\n", emitcode); | 169 | print("\nvoid\n%send(void)\n{\n}\n", emitcode); |
| 159 | for(id = d.ty.ids; id != nil; id = id.next) | ||
| 160 | if(id.store == Dtype && id.ty.kind == Tadt) | ||
| 161 | print("\tfreetype(T_%s);\n", id.sym.name); | ||
| 162 | print("}\n"); | ||
| 163 | } | 170 | } |
| 164 | 171 | ||
| 165 | # | 172 | # |
| 166 | # stub functions | 173 | # stub functions |
| 167 | # | 174 | # |
| 168 | for(id = d.ty.tof.ids; id != nil; id = id.next){ | 175 | for(id = d.ty.tof.ids; id != nil; id = id.next){ |
| 169 | print("\nvoid\n%s_%s(void *fp)\n{\n\tF_%s_%s *f = fp;\n", | 176 | print("\nvoid\n%s_%s(vm_registers_t &r, vm_t &vm)\n{\n auto &fp = r.stack.peek_frame()->base<F_%s_%s>();\n", |
| 170 | id.dot.sym.name, id.sym.name, | 177 | id.dot.sym.name, id.sym.name, |
| 171 | id.dot.sym.name, id.sym.name); | 178 | id.dot.sym.name, id.sym.name); |
| 172 | if(id.ty.tof != tnone && tattr[id.ty.tof.kind].isptr){ | 179 | if(id.ty.tof != tnone && tattr[id.ty.tof.kind].isptr){ |
| 173 | print("\tvoid *r;\n"); | 180 | print("\n //disvm::runtime::dec_ref_count_and_free(vm_alloc_t::from_allocation(*fp.ret));\n //*fp.ret = nullptr;\n"); |
| 174 | print("\n\tr = *f->ret;\n\t*f->ret = H;\n\tdestroy(r);\n"); | ||
| 175 | } | 181 | } |
| 182 | print(" throw vm_system_exception{ \"Function not implemented\" };\n"); | ||
| 176 | print("}\n"); | 183 | print("}\n"); |
| 177 | } | 184 | } |
| 178 | 185 | ||
| @@ -182,14 +189,13 @@ modcode(globals: ref Decl) · 3 unmodified lines | |||
| 182 | 189 | ||
| 183 | modtab(globals: ref Decl) | 190 | modtab(globals: ref Decl) |
| 184 | { | 191 | { |
| 185 | print("typedef struct{char *name; long sig; void (*fn)(void*); int size; int np; uchar map[16];} Runtab;\n"); | ||
| 186 | for(d := globals; d != nil; d = d.next){ | 192 | for(d := globals; d != nil; d = d.next){ |
| 187 | if(d.store == Dtype && d.ty.kind == Tmodule && d.sym.name == emittab){ | 193 | if(d.store == Dtype && d.ty.kind == Tmodule && d.sym.name == emittab){ |
| 188 | n := 0; | 194 | n := 0; |
| 189 | print("Runtab %smodtab[]={\n", d.sym.name); | 195 | print("disvm::runtime::builtin::vm_runtab_t %smodtab[]={\n", d.sym.name); |
| 190 | for(id := d.ty.tof.ids; id != nil; id = id.next){ | 196 | for(id := d.ty.tof.ids; id != nil; id = id.next){ |
| 191 | n++; | 197 | n++; |
| 192 | print("\t\""); | 198 | print(" \""); |
| 193 | if(id.dot != d) | 199 | if(id.dot != d) |
| 194 | print("%s.", id.dot.sym.name); | 200 | print("%s.", id.dot.sym.name); |
| 195 | print("%s\",0x%ux,%s_%s,", id.sym.name, sign(id), | 201 | print("%s\",0x%ux,%s_%s,", id.sym.name, sign(id), |
| @@ -202,8 +208,8 @@ modtab(globals: ref Decl) · 6 unmodified lines | |||
| 202 | } | 208 | } |
| 203 | print("\n"); | 209 | print("\n"); |
| 204 | } | 210 | } |
| 205 | print("\t0\n};\n"); | 211 | print(" 0\n};\n\n"); |
| 206 | print("#define %smodlen %d\n", d.sym.name, n); | 212 | print("const %smodlen = %d\n", d.sym.name, n); |
| 207 | } | 213 | } |
| 208 | } | 214 | } |
| 209 | } | 215 | } |
| @@ -221,14 +227,13 @@ modstub(globals: ref Decl) · 11 unmodified lines | |||
| 221 | s := id.dot.sym.name + "_" + id.sym.name; | 227 | s := id.dot.sym.name + "_" + id.sym.name; |
| 222 | if(emitdyn && id.dot.dot != nil) | 228 | if(emitdyn && id.dot.dot != nil) |
| 223 | s = id.dot.dot.sym.name + "_" + s; | 229 | s = id.dot.dot.sym.name + "_" + s; |
| 224 | print("void %s(void*);\ntypedef struct F_%s F_%s;\nstruct F_%s\n{\n", | 230 | print("void %s(vm_registers_t &, vm_t &);\nstruct F_%s : public vm_frame_base_alloc_t\n{\n", |
| 225 | s, s, s, s); | 231 | s, s); |
| 226 | print(" WORD regs[NREG-1];\n"); | ||
| 227 | if(id.ty.tof != tnone) | 232 | if(id.ty.tof != tnone) |
| 228 | print(" %s* ret;\n", ctypeconv(id.ty.tof)); | 233 | print(" %s* ret;\n", ctypeconv(id.ty.tof)); |
| 229 | else | 234 | else |
| 230 | print(" WORD noret;\n"); | 235 | print(" word_t noret;\n"); |
| 231 | print(" uchar temps[%d];\n", MaxTemp-NREG*IBY2WD); | 236 | print(" byte_t temps[%d];\n", MaxTemp-NREG*IBY2WD); |
| 232 | offset := MaxTemp; | 237 | offset := MaxTemp; |
| 233 | for(m := id.ty.ids; m != nil; m = m.next){ | 238 | for(m := id.ty.ids; m != nil; m = m.next){ |
| 234 | p := ""; | 239 | p := ""; |
| @@ -245,13 +250,13 @@ modstub(globals: ref Decl) · 10 unmodified lines | |||
| 245 | if(offset != m.offset) | 250 | if(offset != m.offset) |
| 246 | yyerror("module stub must not contain data objects"); | 251 | yyerror("module stub must not contain data objects"); |
| 247 | # fatal("modstub bad offset"); | 252 | # fatal("modstub bad offset"); |
| 248 | print(" %s %s;\n", ctypeconv(t), p); | 253 | print(" %s %s;\n", ctypeconv(t), p); |
| 249 | arg++; | 254 | arg++; |
| 250 | offset += t.size; | 255 | offset += t.size; |
| 251 | #ZZZ need to align? | 256 | #ZZZ need to align? |
| 252 | } | 257 | } |
| 253 | if(id.ty.varargs != byte 0) | 258 | if(id.ty.varargs != byte 0) |
| 254 | print(" WORD vargs;\n"); | 259 | print(" byte_t vargs;\n"); |
| 255 | print("};\n"); | 260 | print("};\n"); |
| 256 | } | 261 | } |
| 257 | for(id = d.ty.ids; id != nil; id = id.next) | 262 | for(id = d.ty.ids; id != nil; id = id.next) |
| @@ -262,10 +267,9 @@ modstub(globals: ref Decl) · 4 unmodified lines | |||
| 262 | 267 | ||
| 263 | chanstub(in: string, id: ref Decl) | 268 | chanstub(in: string, id: ref Decl) |
| 264 | { | 269 | { |
| 265 | print("typedef %s %s_%s;\n", ctypeconv(id.ty.tof), in, id.sym.name); | 270 | print("using %s_%s = %s;\n", in, id.sym.name, ctypeconv(id.ty.tof)); |
| 266 | desc := mktdesc(id.ty.tof); | 271 | desc := mktdesc(id.ty.tof); |
| 267 | print("#define %s_%s_size %d\n", in, id.sym.name, desc.size); | 272 | print("const byte_t %s_%s_map = %s;\n", in, id.sym.name, mapconv(desc)); |
| 268 | print("#define %s_%s_map %s\n", in, id.sym.name, mapconv(desc)); | ||
| 269 | } | 273 | } |
| 270 | 274 | ||
| 271 | # | 275 | # |
| @@ -287,13 +291,13 @@ adtstub(globals: ref Decl) · 15 unmodified lines | |||
| 287 | s := dotprint(d.ty.decl, '_'); | 291 | s := dotprint(d.ty.decl, '_'); |
| 288 | case d.ty.kind{ | 292 | case d.ty.kind{ |
| 289 | Tadt => | 293 | Tadt => |
| 290 | print("typedef struct %s %s;\n", s, s); | 294 | ; |
| 291 | Tint or | 295 | Tint or |
| 292 | Tbyte or | 296 | Tbyte or |
| 293 | Treal or | 297 | Treal or |
| 294 | Tbig or | 298 | Tbig or |
| 295 | Tfix => | 299 | Tfix => |
| 296 | print("typedef %s %s;\n", ctypeconv(t), s); | 300 | print("using %s = %s;\n", ctypeconv(t), s); |
| 297 | } | 301 | } |
| 298 | } | 302 | } |
| 299 | } | 303 | } |
| @@ -319,12 +323,12 @@ adtstub(globals: ref Decl) · 19 unmodified lines | |||
| 319 | (offset, nil) = stubalign(offset, tt.align, nil); | 323 | (offset, nil) = stubalign(offset, tt.align, nil); |
| 320 | if(offset != id.offset) | 324 | if(offset != id.offset) |
| 321 | fatal("adtstub bad offset"); | 325 | fatal("adtstub bad offset"); |
| 322 | print(" %s %s;\n", ctypeconv(tt), id.sym.name); | 326 | print(" %s %s;\n", ctypeconv(tt), id.sym.name); |
| 323 | offset += tt.size; | 327 | offset += tt.size; |
| 324 | } | 328 | } |
| 325 | } | 329 | } |
| 326 | if(t.ids == nil){ | 330 | if(t.ids == nil){ |
| 327 | print(" char dummy[1];\n"); | 331 | print(" char dummy[1];\n"); |
| 328 | offset = 1; | 332 | offset = 1; |
| 329 | } | 333 | } |
| 330 | (offset, nil)= stubalign(offset, t.align, nil); | 334 | (offset, nil)= stubalign(offset, t.align, nil); |
| @@ -345,8 +349,7 @@ adtstub(globals: ref Decl) · 14 unmodified lines | |||
| 345 | desc := mktdesc(t); | 349 | desc := mktdesc(t); |
| 346 | if(offset != desc.size && t.ids != nil) | 350 | if(offset != desc.size && t.ids != nil) |
| 347 | fatal("adtstub: bad desc size"); | 351 | fatal("adtstub: bad desc size"); |
| 348 | print("#define %s_size %d\n", s, offset); | 352 | print("const byte_t %s_map[] = %s;\n", s, mapconv(desc)); |
| 349 | print("#define %s_map %s\n", s, mapconv(desc)); | ||
| 350 | #ZZZ | 353 | #ZZZ |
| 351 | if(0) | 354 | if(0) |
| 352 | print("struct %s_check {int s[2*(sizeof(%s)==%s_size)-1];};\n", s, s, s); | 355 | print("struct %s_check {int s[2*(sizeof(%s)==%s_size)-1];};\n", s, s, s); |
| @@ -367,9 +370,9 @@ stubalign(offset: int, a: int, s: string): (int, string) · 14 unmodified lines | |||
| 367 | return (offset, s); | 370 | return (offset, s); |
| 368 | x = a - x; | 371 | x = a - x; |
| 369 | if(s != nil) | 372 | if(s != nil) |
| 370 | s += sprint("uchar\t_pad%d[%d]; ", offset, x); | 373 | s += sprint("byte_t _pad%d[%d]; ", offset, x); |
| 371 | else | 374 | else |
| 372 | print("\tuchar\t_pad%d[%d];\n", offset, x); | 375 | print(" byte_t _pad%d[%d];\n", offset, x); |
| 373 | offset += x; | 376 | offset += x; |
| 374 | if((offset & (a-1)) || x >= a) | 377 | if((offset & (a-1)) || x >= a) |
| 375 | fatal("compiler stub misalign"); | 378 | fatal("compiler stub misalign"); |
| @@ -381,16 +384,16 @@ constub(id: ref Decl) · 5 unmodified lines | |||
| 381 | s := id.dot.sym.name + "_" + id.sym.name; | 384 | s := id.dot.sym.name + "_" + id.sym.name; |
| 382 | case id.ty.kind{ | 385 | case id.ty.kind{ |
| 383 | Tbyte => | 386 | Tbyte => |
| 384 | print("#define %s %d\n", s, int id.init.c.val & 16rff); | 387 | print("const byte_t %s = %d;\n", s, int id.init.c.val & 16rff); |
| 385 | Tint or | 388 | Tint or |
| 386 | Tfix => | 389 | Tfix => |
| 387 | print("#define %s %d\n", s, int id.init.c.val); | 390 | print("const word_t %s = %#x;\n", s, int id.init.c.val); |
| 388 | Tbig => | 391 | Tbig => |
| 389 | print("#define %s %bd\n", s, id.init.c.val); | 392 | print("const big_t %s %bd;\n", s, id.init.c.val); |
| 390 | Treal => | 393 | Treal => |
| 391 | print("#define %s %g\n", s, id.init.c.rval); | 394 | print("const real_t %s = %.16g;\n", s, id.init.c.rval); |
| 392 | Tstring => | 395 | Tstring => |
| 393 | print("#define %s \"%s\"\n", s, id.init.decl.sym.name); | 396 | print("const char *%s = \"%s\";\n", s, id.init.decl.sym.name); |
| 394 | } | 397 | } |
| 395 | } | 398 | } |
| 396 | 399 | ||
| @@ -422,20 +425,20 @@ ckindname := array[Tend] of · 25 unmodified lines | |||
| 422 | Tnone => "void", | 425 | Tnone => "void", |
| 423 | Tadt => "struct", | 426 | Tadt => "struct", |
| 424 | Tadtpick => "?adtpick?", | 427 | Tadtpick => "?adtpick?", |
| 425 | Tarray => "Array*", | 428 | Tarray => "vm_array_t", |
| 426 | Tbig => "LONG", | 429 | Tbig => "big_t", |
| 427 | Tbyte => "BYTE", | 430 | Tbyte => "byte_t", |
| 428 | Tchan => "Channel*", | 431 | Tchan => "vm_channel_t", |
| 429 | Treal => "REAL", | 432 | Treal => "real_t", |
| 430 | Tfn => "?fn?", | 433 | Tfn => "?fn?", |
| 431 | Tint => "WORD", | 434 | Tint => "word_t", |
| 432 | Tlist => "List*", | 435 | Tlist => "vm_list_t", |
| 433 | Tmodule => "Modlink*", | 436 | Tmodule => "vm_module_ref_t", |
| 434 | Tref => "?ref?", | 437 | Tref => "?ref?", |
| 435 | Tstring => "String*", | 438 | Tstring => "vm_string_t", |
| 436 | Ttuple => "?tuple?", | 439 | Ttuple => "?tuple?", |
| 437 | Texception => "?exception", | 440 | Texception => "?exception", |
| 438 | Tfix => "WORD", | 441 | Tfix => "word_t", |
| 439 | Tpoly => "void*", | 442 | Tpoly => "void*", |
| 440 | 443 | ||
| 441 | Tainit => "?ainit?", | 444 | Tainit => "?ainit?", |
| @@ -463,29 +466,29 @@ ctypeconv(t: ref Type): string · 21 unmodified lines | |||
| 463 | Terror => | 466 | Terror => |
| 464 | return "type error"; | 467 | return "type error"; |
| 465 | Tref => | 468 | Tref => |
| 466 | s = ctypeconv(t.tof); | 469 | return "/* " + ctypeconv(t.tof) + " */ pointer_t"; |
| 467 | s += "*"; | ||
| 468 | Tarray or | ||
| 469 | Tlist or | ||
| 470 | Tint or | 470 | Tint or |
| 471 | Tbig or | 471 | Tbig or |
| 472 | Tstring or | ||
| 473 | Treal or | 472 | Treal or |
| 474 | Tbyte or | 473 | Tbyte or |
| 475 | Tnone or | 474 | Tnone or |
| 476 | Tany or | 475 | Tany or |
| 477 | Tchan or | ||
| 478 | Tmodule or | ||
| 479 | Tfix or | 476 | Tfix or |
| 480 | Tpoly => | 477 | Tpoly => |
| 481 | return ckindname[t.kind]; | 478 | return ckindname[t.kind]; |
| 479 | Tarray or | ||
| 480 | Tlist or | ||
| 481 | Tstring or | ||
| 482 | Tchan or | ||
| 483 | Tmodule => | ||
| 484 | return "/* " + ckindname[t.kind] + " */ pointer_t"; | ||
| 482 | Tadtpick => | 485 | Tadtpick => |
| 483 | return ctypeconv(t.decl.dot.ty); | 486 | return ctypeconv(t.decl.dot.ty); |
| 484 | Tadt or | 487 | Tadt or |
| 485 | Ttuple => | 488 | Ttuple => |
| 486 | if(t.decl.sym != anontupsym) | 489 | if(t.decl.sym != anontupsym) |
| 487 | return dotprint(t.decl, '_'); | 490 | return dotprint(t.decl, '_'); |
| 488 | s += "struct{ "; | 491 | s += "struct { "; |
| 489 | offset := 0; | 492 | offset := 0; |
| 490 | for(id := t.ids; id != nil; id = id.next){ | 493 | for(id := t.ids; id != nil; id = id.next){ |
| 491 | tt := id.ty; | 494 | tt := id.ty; |